優先佇列的基本資料結構(2)
阿新 • • 發佈:2019-02-07
摘要:本次提供另外一些優先佇列的基本操作
【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);
}