堆的特性:
1.结构性:是一个完全二叉树(所以可以用数组储存)
2.有序性:任意结点的关键字都是其子树所有结点的最大值
用数组的方式来表示最大堆
typedef int ElementType;
#define MaxDate 100000;
typedef struct HeapStruct{
ElementType *Elements;
int Size;//当前元素个数
int Capacity;//堆的容量
}*MaxHeap;
最大堆的操作:
创建一个最大堆
MaxHeap Create(int MaxSize)
{
MaxHeap H=(MaxHeap)malloc(sizeof(HeapStruct));
H->Elements=(ElementType *)malloc(sizeof(ElementType)*(MaxSize+1));
H->Size=0;
H->Capacity=MaxSize;
H->Elements[0]=MaxDate;//哨兵
return H;
}
最大堆的插入
算法:将新增结点插入到其父节点到根结点的这条路径上
void Insert(MaxHeap H,ElementType Item)
{
int i=++H->Size;
for(;H->Elements[i/2]<Item;i/=2)//i向上移
{
H->Elements[i]=H->Elements[i/2];//父节点向下移
}
H->Elements[i]=Item;
}
最大堆的删除
算法:将最后一个结点替换到根结点的位置,然后与其左右儿子中较大的比较,如果父节点小,则将儿子结点向上移
父节点向下移。否则找到正确的位置。时间复杂度为logn。
ElementType Delete(MaxHeap H)
{
int parent,child;
ElementType MaxItem,term;
MaxItem = H->Elements[1];
term=H->Elements[H->Size--];
for(parent=1;2*parent<=H->Size;parent=child)//parent指示要移动到的位置,位置向下移
{
child = 2*parent;
if(child+1<=H->Size&&H->Elements[child]<H->Elements[child+1])
child++;//child指示左右儿子中较大的那个
if(term>=H->Elements[child])
break;
else
{
H->Elements[parent]=H->Elements[child];//儿子向上移
}
}
H->Elements[parent]=term;
return MaxItem;
}
最大堆的建立
算法1:将给定元素一个一个插入到最大堆中,每个元素插入的时间复杂度为O(logn),一共n个元素,总体时间复杂度为O(nlog(n))
算法2:将给定元素依次进入堆中,满足最大堆结构特性。再从最后一个父节点开始调整(调整策略同删除操作,即向下过滤)。时间复杂度为O(n)
MaxHeap BuildMaxHeap( MaxHeap H )
{ /* 这里假设所有H->Size个元素已经存在H->Elements[]中 */
/* 本函数将H->Elements[]中的元素调整,使满足最大堆的有序性 */
int Parent, Child, i;
ElementType temp;
for( i = H->Size/2; i>0; i-- )
{ /*从最后一个结点的父结点开始调整 */
temp = H->Elements[i];
for( Parent=i; Parent*2<=H->Size; Parent=Child ) { /* 向下过滤 */
Child = Parent * 2;
if( (Child!= H->Size) && (H->Elements[Child] < H->Elements[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( temp >= H->Elements[Child] ) break;
else /* 移动temp元素到下一层 */
H->Elements[Parent] = H->Elements[Child];
} /* 结束内部for循环对以H->Elements[i]为根的子树的调整 */
H->Elements[Parent] = temp;
}
return H;
}