二項堆其實就是由多棵二項樹構成的森林,每棵樹的根結點構成乙個單鏈表。其鍊錶序列,按照每棵二項樹的度從小到大排列。
依然分析它的五種基本操作:
說說二項樹。
圖為一顆b3:
說說二項堆,二項堆作為乙個二項樹的集合,按照根結點的度數大小從小到大排列,每棵二項樹都滿足堆的性質(以下以最小堆性質為例),同時二項堆裡不能有兩棵或以上具有相同度數的二項樹。
形如:
對每個結點做如下定義:
1 typedef struct建立新堆只需要分配乙個二項堆的結點。生成乙個堆物件便可。所以時間複雜度為o(1)。node bnode, *bheap;
1 bnode *make_node(int合併兩個二項堆。時間複雜度為o(logn)key)
圖示
**實現
1有了合併操作,插入操作也就很好實現了,只需要將新加入的結點與原二項堆合併即可。時間複雜度等同於union,為o(logn)//合併兩個根節點鍊錶
2 bnode *merge(bheap h1, bheap h2) else
13return
head;14}
1516
//將兩個相鄰的根樹合併
17void
link(bheap child, bheap heap)
2324
//合併
25 bnode *union(bheap h1, bheap h2) else
if (x->key <= nxt_x->key) else
49 nxt_x = x->next;50}
51return
heap;
52 }
**實現
1 bnode *insert(bheap heap, int對於二項堆,其最小結點必然在根煉表中,所以只要遍歷一遍根鍊錶就可以找到。根煉表由logn個結點組成,所以時間複雜度為o(logn),如果在其他操作中設定乙個指標反覆更新最小結點位置,那麼時間複雜度可以壓縮至o(1)。key)
**實現
1 bnode *minimun(bheap heap)移除最小結點,因為最小結點必然在根煉表中,所以此操作可以:8return
minn;
9 }
時間複雜度o(logn)。
圖示
**實現
1//將子樹們轉換成乙個新的二項堆
2 bnode *transform(bheap heap)
14 heap->next =tail;
15return
heap;16}
1718
//刪除最小堆頂元素
19 bnode *extract_min(bheap heap)
28if (pre) pre->next = minnode->next;
29else heap = minnode->next;
30 heap = union(heap, transform(minnode->child));
31delete
(minnode);
32return
heap;
33 }
半路演算法之二項樹與二項堆
秉承前文。前面提到過針對稀疏圖時,以二項堆來作為最小優先佇列是更為適宜的。這裡記錄一下學習二項堆的過程。二項堆的名字 於二項樹。二項堆是多個二項樹連在了一起。二項樹的名字 於其bn 棵樹的元素個數為2n 且其深度n處恰有2k 個節點,其性質與二項式非常吻合。此外,它還是一種遞迴定義的有序樹。重點依照...
heap的一些實現,二叉堆,左式堆,二項佇列
這裡的堆指的都是二叉堆,為了優先佇列產生 優先佇列,使一些特殊的結點在出隊的時候要優先出來。出隊入隊操作變成了insert和delete 堆是乙個完全二叉樹,除了最後一層,其餘層都是滿的。這樣的話儲存用乙個陣列就可以,任乙個元素位置在i,其左兒子位置是2 i,右兒子位置是2 i 1,父結點是i 2向...
資料結構與演算法 二項佇列與二叉堆的比較
二叉堆確實是入門級的重要資料結構了,而二項佇列也是慢慢要去掌握的一種支援高效合併的優先佇列實現。本文稍作比較,望拋磚引玉。基本操作 insert 平均 deletemin deletemax merge 二項佇列 o 1 o logn o logn 二叉堆 o 1 o logn o n 不難看出,二...