1. 程式人生 > >優先佇列的基本資料結構(2)

優先佇列的基本資料結構(2)

摘要:本次提供另外一些優先佇列的基本操作
【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);
}