摘要:本次提供另外一些优先队列的基本操作
【1】
对二叉堆进行下滤,就是让某个元素降至到使得它符合二叉堆优先结构的节点.
void PerLocateDown(Heap H,int i)
//对二叉堆进行下滤
{
int child;
int FirstElement = H->Element[i];
for(;i*2<= H->heapsize; i = child )
{
//for循环 一直到满足堆序或者到底层
//获取最小儿子
child = i*2;
if (child != H->heapsize && H->Element[child+1]<H->Element[child] )
child++;
if(FirstElement > H->Element[child])
{
//不满足堆序,交换节点
H->Element[i] = H->Element[child];
}
else
break;//满足堆序
}
H->Element[i] = FirstElement;
}
【2】对二叉堆进行上滤,使得它上升到某个符合堆序的位置;
void PerLocateUp(Heap H,int i )
{
//将一个元素【i】上滤
int LastElement = H->Element[i];
for(; LastElement < H->Element[i/2]; i /=2)
{
H->Element[i] = H->Element[i/2];
}
H->Element[i] = LastElement;
}
【3】
有很多时候,我们需要降低或者增加一个节点元素的值,那么降值之后,应该进行上滤.而升值之后,就应该进行下滤.
void DecreaseKey(int P,int delta,Heap H)
{
if (delta < 0 )
delta = -1*delta;
if(P<=H->heapsize)
{
H->Element[P] -= delta;
PerLocateUp(H,P);
}
else
{
puts("the Position is too large");
exit(1);
}
}
【4】
最后是创建一个堆的操作.最容易想到的办法是连续进行N次插入操作(这样的操作有NlogN的时间界).但是我们可以思考,是否存在使得时间界是O(N)方法呢?实际上是有的。
{1}首先直接插入所有想要的数据,这将花费O(N)的时间。接着对倒数第二层开始的所有节点(N/2)进行下滤,可以证明所有比较的次数也将是O(N)。
Heap BuildHeap(int *A,int N)//将N个关键字放入H里
{
Heap H = Initialize(N);
H->heapsize = N;
for(int i = 1;i <= N;i++)
H->Element[i] = A[i-1];
for(int j = N/2;j>=1; j --)
PerLocateDown(H,j);
return H;
}
[5]最后的一种操作则是进行删除一个固定的节点而不是最小的节点。所以先用Decreasekey将操作降到最小,然后用DeleteMin操作删除.
void Delete(int P,Heap H)
{
int delta = H->Element[P] - H->Element[1] + 1;//delta使得key比H->Element[1]小
DecreaseKey(P,delta,H);
DeleteMin(H);
}
来源:CSDN
作者:PYB不开心
链接:https://blog.csdn.net/pp634077956/article/details/48175037