您的位置:首页 > 其它

最大堆/最小堆、siftup和siftdown

2014-02-26 16:48 281 查看
从数据的存储结构看,最大堆/最小堆是一个数组。
从数据的逻辑结构看,最大堆/最小堆是一棵完全二叉树。

堆有以下三种基本操作:
1.初始化:将一个无序的序列初始化成堆。从最后一个非叶子结点(namely, (max_index-1)/2)开始,自右向左,自下向上,对每一个根结点执行siftdown操作。O(N)。
2.插入。在数组的末尾插入新的元素,然后执行siftup操作。O(logN)。
3.删除。删除指定位置的元素,用数组末尾的元素代替。然后视情况执行siftup或者siftdown操作(注意这两个操作是互斥的,只能执行其中之一)。O(logN)。

当前元素若可能与下一层元素交换,就是siftdown;若可能与上一层元素交换,就是siftup。或者说当前元素被“挖出”后形成的“坑”,若往上升就是siftup,若往下降就是siftdown。

以下是siftup和siftdown的代码(以最小堆为例):
void siftup(int position)
{
int child=position;
int father=(child-1)/2;

int temp=minheap[position];    //把要处理的元素“挖出来”,形成一个“坑”

while(father>=0 && child>=1)
{
if(minheap[father]>temp)
{
minheap[child]=minheap[father];    //“坑”往上升

child=father;    //更新下标
father=(child-1)/2;
}
else
break;
}

minheap[child]=temp;    //把temp填回“坑”里去
}

void siftdown(int position, int heapsize)
{
int father=position;
int child=father*2+1;

int temp=minheap[position];    //仍然是挖坑

while(child<heapsize)
{
if(child<heapsize-1 && minheap[child]>minheap[child+1])    //两个儿子较小的哪一个
child=child+1;

if(temp>minheap[child])
{
minheap[father]=minheap[child];    //坑往下沉

father=child;    //更新下标
child=2*father+1;
}
else
break;
}

minheap[father]=temp;    //填坑
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息