1.概览
- 由于堆是一棵完全二叉树,所以可以使用vector存储数据
- (0位置不放数据) 任意
节点i
,其左儿子为2i
,其右儿子为2i+1
,其父亲为i/2(下取整)
- 堆算法主要包含三个:插入(上滤操作)、删除(下滤操作)、建堆(循环下滤操作)
2.上滤即插入的过程
- 主要思想:当要插入元素x时,在最后的位置建立一个空穴,判断该空穴是否能放下x,若不能,则上滤空穴(即将父亲的值填入空穴,而将父亲作为新的空穴)持续上述过程,直到找到合适位置
void insert(ElementType& x,priorityQueue H)
{
int i;
for(int i=++H->size;H->Elements[i/2]>x;i/=2)
H->Elements[i]=H->Elements[i/2];
H->Elements[i]=x;
}
3.下滤,即删除过程
- 主要思想:heap值允许删顶部的元素,删除过程为,将根节点设为空穴,现在的目的是要给最底层最右侧(最后一个元素)找到一个合适的位置。将最后一个值与空穴的儿子中较大/小的一个(视最大堆、最小堆情况而定)比较,若能放下最后一个元素,则结束;否则,将空穴下滤,直至找到合适位置
ElementType DeleteMin(PriorityQueue H)
{
int i,child;
ElementType MinElement,LastElement;
if(IsEmpty(H))
{
return H->Elements[0];
}
MinElement=H->Elements[1];
LastElement=H->Elements[H->size--];
for(i=1;i*2<=H->size;i=child)
{
child=i*2;
if(child!=H->size && H->Elements[child+1]<H->Elements[child])
child++;
if(LastElement>H->Elements[child])
H->Elements[i]=H->Elements[child];
else
break;
}
H->Elements[i]=LastElements;
return MinElements;
}
4. 建堆
- 主要思想:先将所有数据填入vector中,从size/2的位置开始,将自身视为空穴,开始下滤操作
...
ElementType copy;
for(int i=H->size/2;i>0;--i)
{
copy=H->Elements[i];
int j;
for(j=i;j*2<=H->size;j=child)
{
child=j*2;
if(child!=H->size && H->Elements[child+1]<H->Elements[child])
child++;
if(LastElement>H->Elements[child])
H->Elements[j]=H->Elements[child];
else
break;
}
H->Elements[j]=copy;
}
4.堆排序
- 先将待排序序列放入vector中
- 使用建堆算法,建立一个最小/大堆
- 依次删除根节点元素,并非真的删除,而是将其放在当前队列的最末端,并堆的大小减一,之后调整堆的结构,继续执行此步骤
- 直至堆的大小为0,排序完成