C++二叉树的应用(一):堆及其操作
作者:互联网
本文为浙大版《数据结构》学习笔记。
堆(Heap)又称为优先队列,队列中元素的进出依据先进先出的原则,而在堆中,取出元素时依照元素优先级的大小。
堆最常用的结构是用二叉树表示,通常是用完全二叉树,由于完全二叉树中结点排布极其规律,因而可直接用数组实现其存储。
由此,堆有两个特性:
1.结构特性:用数组表示完全二叉树;
2.部分有序性:任一结点元素的数值与其子结点所存储的值是相关的。
有两种基本堆:最小堆(MinHeap)和最大堆(MaxHeap)。在前者中,任一结点的值大于或等于其子结点的值;在后者中,任一结点的值小于或等于其子结点的值。
这里仅以最大堆的操作为例。
1.堆的结构定义
struct Heap
{
ElementType *Data;
int Size; //标记当前元素数
int Capacity; //标记最大容量
};
typedef Heap MaxHeap;
typedef Heap MinHeap;
2.初始化堆
/*初始化堆*/
MaxHeap *InitiateHeap(int MaxSize)
{
MaxHeap *H=new MaxHeap;
H->Data=new ElementType[MaxSize+1];
H->Size=0;
H->Capacity=MaxSize;
H->Data[0]=MAXDATE;
return(H);
}
3.判断堆满
/*判断堆满*/
bool IsFull(MaxHeap *H)
{
return(H->Size==H->Capacity);
}
4.判断堆空
/*判断堆空*/
bool IsEmpty(MaxHeap *H)
{
return(H->Size==0);
}
5.在堆中插入元素X
/*在最大堆中插入X*/
void Insert(MaxHeap *H,ElementType X)
{
int i;
if(IsFull(H)){
cout<<"堆已满"<<endl;
return;
}
i=++H->Size; //i指向新增元素的位置
for(;H->Data[i/2]<X;i/=2)
H->Data[i]=H->Data[i/2]; //将元素X插入的位置上移
H->Data[i]=X;
}
6.取出键值为最大的元素,并删除一个结点
/*取出键值为最大的元素,并删除一个结点*/
ElementType DeleteMax(MaxHeap *H)
{
int Parent,Child;
ElementType MaxItem,X;
if(IsEmpty(H)){
cout<<"堆已空"<<endl;
return ERROR;
}
MaxItem=H->Data[1];
X=H->Data[H->Size--];
for(Parent=1;Parent*2<=H->Size;Parent=Child){ //循环条件:判断左儿子是否存在
Child=Parent*2; //Child指向左儿子
if((Child!=H->Size) && (H->Data[Child]<H->Data[Child+1])) //右儿子存在,且右儿子比左儿子大
Child++;
if(X>=H->Data[Child])
break;
else
H->Data[Parent]=H->Data[Child]; //将元素X存放的位置下移
}
H->Data[Parent]=X;
return(MaxItem);
}
7.将已有堆调整成最大堆:1.先保证结构特性(完全二叉树);2.再调整有序性
/*将已有堆调整成最大堆:1.先保证结构特性(完全二叉树);2.再调整有序性*/
void BuildHeap(MaxHeap *H)
{
int i;
for(i=H->Size/2;i>0;i--) //从最后一个父结点开始
PercDown(H,i);
}
PercDown()函数
/*将H中以H->Data[p]为根的子堆调整为最大堆*/
void PercDown(MaxHeap *H,int p)
{
int Parent,Child;
ElementType X;
X=H->Data[p];
for(Parent=p;Parent*2<=H->Size;Parent=Child){
Child=Parent*2;
if((Child!=H->Size)&&(H->Data[Child]<H->Data[Child+1]))
Child++;
if(X>=H->Data[Child])
break;
else
H->Data[Parent]=H->Data[Child];
}
H->Data[Parent]=X;
}
一个可运行的完整程序:
根据输入的元素创建一个最大堆,再插入数值58,再删除堆中最大的元素,最后打印出堆中的所有元素。
#include <iostream>
#define MAXDATE 100
#define ERROR -1;
using namespace std;
typedef int ElementType;
struct Heap
{
ElementType *Data;
int Size; //标记当前元素数
int Capacity; //标记最大容量
};
typedef Heap MaxHeap;
typedef Heap MinHeap;
int main()
{
MaxHeap *InitiateHeap(int MaxSize);
void Insert(MaxHeap *H,ElementType X);
void BuildHeap(MaxHeap *H);
ElementType DeleteMax(MaxHeap *H);
int MaxSize;
cin>>MaxSize;
MaxHeap *H;
H=InitiateHeap(MaxSize);
ElementType X;
cout<<"X=";
cin>>X;
while(X!=0){
H->Data[++H->Size]=X;
cout<<"X=";
cin>>X;
}
BuildHeap(H);
Insert(H,58);
DeleteMax(H);
int i;
for(i=1;i<=H->Size;i++)
cout<<H->Data[i]<<' ';
cout<<endl;
return 0;
}
/*初始化堆*/
MaxHeap *InitiateHeap(int MaxSize)
{
MaxHeap *H=new MaxHeap;
H->Data=new ElementType[MaxSize+1];
H->Size=0;
H->Capacity=MaxSize;
H->Data[0]=MAXDATE;
return(H);
}
/*判断堆满*/
bool IsFull(MaxHeap *H)
{
return(H->Size==H->Capacity);
}
/*判断堆空*/
bool IsEmpty(MaxHeap *H)
{
return(H->Size==0);
}
/*在最大堆中插入X*/
void Insert(MaxHeap *H,ElementType X)
{
int i;
if(IsFull(H)){
cout<<"堆已满"<<endl;
return;
}
i=++H->Size; //i指向新增元素的位置
for(;H->Data[i/2]<X;i/=2)
H->Data[i]=H->Data[i/2]; //将元素X插入的位置上移
H->Data[i]=X;
}
/*取出键值为最大的元素,并删除一个结点*/
ElementType DeleteMax(MaxHeap *H)
{
int Parent,Child;
ElementType MaxItem,X;
if(IsEmpty(H)){
cout<<"堆已空"<<endl;
return ERROR;
}
MaxItem=H->Data[1];
X=H->Data[H->Size--];
for(Parent=1;Parent*2<=H->Size;Parent=Child){ //循环条件:判断左儿子是否存在
Child=Parent*2; //Child指向左儿子
if((Child!=H->Size) && (H->Data[Child]<H->Data[Child+1])) //右儿子存在,且右儿子比左儿子大
Child++;
if(X>=H->Data[Child])
break;
else
H->Data[Parent]=H->Data[Child]; //将元素X存放的位置下移
}
H->Data[Parent]=X;
return(MaxItem);
}
/*将H中以H->Data[p]为根的子堆调整为最大堆*/
void PercDown(MaxHeap *H,int p)
{
int Parent,Child;
ElementType X;
X=H->Data[p];
for(Parent=p;Parent*2<=H->Size;Parent=Child){
Child=Parent*2;
if((Child!=H->Size)&&(H->Data[Child]<H->Data[Child+1]))
Child++;
if(X>=H->Data[Child])
break;
else
H->Data[Parent]=H->Data[Child];
}
H->Data[Parent]=X;
}
/*将已有堆调整成最大堆:1.先保证结构特性(完全二叉树);2.再调整有序性*/
void BuildHeap(MaxHeap *H)
{
int i;
for(i=H->Size/2;i>0;i--) //从最后一个父结点开始
PercDown(H,i);
}
运行结果(红框内为输出):
标签:Parent,int,MaxHeap,C++,二叉树,应用,Child,Data,Size 来源: https://blog.csdn.net/MilkLeong/article/details/104409046