優先隊列/堆的基礎

優先隊列(堆)的定義和性質

定義:
優先隊列: 特殊的“隊列”,取出元素的順序是按照它的優先級大小,而不是元素進入隊列的先後順序。

使用堆來實現優先隊列。
性質:

  1. 結構性:用數組表示的完全二叉樹。
  2. 有序性:任一結點是其子樹所有結點的最大值(或最小值)。
    最大堆:maxHeap,也叫大頂堆
    最小堆:minHeap,也叫小頂堆
  3. 從根結點到任意結點的路徑上,都是有序的。

基礎操作

下面以大頂堆爲例進行說明

1.初始化

  • 堆可以用數組實現
  • 數組的第0個元素可以作爲“哨兵”,不存儲實際使用的值,用來簡化堆中的一些操作。比如存一個後面結點永遠比它小的值(MAX_VALUE),這樣可以方便後面的插入操作。

init

2. 插入

  1. 在數組後面插入新值
  2. 從新值從下往上進行調整,只要它比父結點大,父結點就往下移動;否則停止,將該值放到對應的位置

insert

3.刪除堆頂元素(刪除最大值)

  1. 記錄堆頂元素。
  2. 將堆的最後一個元素放到堆頂。然後進行堆的調整。
  3. 從根結點開始,取它的左右子節點的最大值,看子節點是否比它大,如果子節點更大,將子節點往上移動,然後再看子節點的左右子節點,直到葉子節點或者左右子節點比該值小。

deleteMax

4.堆的構建

方式一: 循環插入 O(N*logN),將元素一個一個插入初始爲空的堆中。
方式二:首先將N個元素順序存入數組,先滿足完全二叉樹的性質;然後再從n/2的位置開始調整堆,使之符合有序性。每次調整都是 左右兩個子樹原本都是堆,然後將根結點進行調整。類似於刪除最大元素之後的調整。時間複雜度O(n)。

/*----------- 建造最大堆 -----------*/
void PercDown( MaxHeap H, int p )
{ /* 下濾:將H中以H->Data[p]爲根的子堆調整爲最大堆 */
    int Parent, Child;
    ElementType X;
 
    X = H->Data[p]; /* 取出根結點存放的值 */
    for( Parent=p; Parent*2<=H->Size; Parent=Child ) {
        Child = Parent * 2;
        if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
            Child++;  /* Child指向左右子結點的較大者 */
        if( X >= H->Data[Child] ) break; /* 找到了合適位置 */
        else  /* 下濾X */
            H->Data[Parent] = H->Data[Child];
    }
    H->Data[Parent] = X;
}
 
void BuildHeap( MaxHeap H )
{ /* 調整H->Data[]中的元素,使滿足最大堆的有序性  */
  /* 這裏假設所有H->Size個元素已經存在H->Data[]中 */
    int i;
    /* 從最後一個結點的父節點開始,到根結點1 */
    for( i = H->Size/2; i>0; i-- )
        PercDown( H, i );
}

計算時間複雜度

發佈了90 篇原創文章 · 獲贊 46 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章