二項堆:ios
1.二項堆是由一些二項樹鏈接而成,每一棵二項樹都遵循最小堆性質(即關鍵字的節點大於等於其父親幾點)函數
2.對任意的度數k,一個二項堆至多有一棵二項樹的根度數爲k (說明一個二項堆最多隻有lgn+1棵二項樹,spa
將n寫成二進制,每個值爲1的位對應一棵二項樹);code
二項堆中的各二項樹的根被組織成一個鏈表,稱爲根表,且各根的度數是嚴格遞增的blog
操做:排序
1.建堆操做:Make-Heap 時間複雜度: O(1)ci
2.返回最小元素: Minumum lgnstring
過程:掃描一遍根表便可找出最小值,每棵二項樹的最小值都在根節點處;io
3.合併兩個二項堆: Union lgnclass
合併過程:先將兩個二項堆的二項樹按度數排序鏈接成一個,而後從Head開始掃描根表,遇到相鄰度數
相等的二項樹就將其合併爲一棵二項樹,分爲4種狀況。
合併須要用到兩個輔助函數:
1.Binomial_Link() : 合併兩棵二項樹 O(1)
2.Binomal-Heap-Merge(): 將兩個二項堆的各二項樹按度數從小到大排序鏈接起來 lgn
4.插入新元素 Insert lgn
過程: 插入過程實際上是先爲新元素單獨建一個二項堆,而後調用Union操做將該二項堆與原來的二項堆合
並起來。
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 const int INF = 1000000; 5 struct Node { 6 int data, degree; 7 Node *p, *child, *sibling; 8 Node(int data_, int degree_, Node* p_, Node* child_, Node* sibling_) { 9 data = data_; degree = degree_; p = p_; 10 child = child_; sibling = sibling_; 11 } 12 }; 13 //新建二叉堆 14 Node* Make_Binomial_Heap() { 15 Node* Binomial_Heap = NULL; 16 return Binomial_Heap; 17 } 18 //返回最小元素 19 Node* Binomial_Heap_Minimum(Node* &H) { 20 Node *x = H, *y = NULL; 21 int min = INF; 22 while (x != NULL) { 23 if (x->data < min) { 24 min = x->data; 25 y = x; 26 } 27 x = x->sibling; 28 } 29 return y; 30 } 31 //基本操做:鏈接兩棵二項樹 32 Node* Binomial_Link(Node* &y, Node* &z) { 33 y->p = z; 34 y->sibling = z->child; 35 z->child = y; 36 z->degree += 1; 37 } 38 //將H1和H2的根表合併成一個按度數單調遞增次序排列的鏈表 39 Node* Binomial_Heap_Merge(Node* &H1, Node* &H2) { 40 Node* H = NULL, *ptr = NULL; 41 Node* ptr1 = H1, *ptr2 = H2; 42 while (ptr1 || ptr2) { 43 if (ptr1 == NULL || (ptr2 && ptr1->data > ptr2->data)) { 44 if (H == NULL) { 45 ptr = ptr2; H = ptr; ptr2 = ptr2->sibling; 46 } else { 47 ptr->sibling = ptr2; ptr = ptr->sibling; ptr2 = ptr2->sibling; 48 } 49 } else if (ptr2 == NULL || (ptr1 && ptr1->data <= ptr2->data)) { 50 if (H == NULL) { 51 ptr = ptr1; H = ptr; ptr1 = ptr1->sibling; 52 } else { 53 ptr->sibling = ptr1; ptr = ptr->sibling; ptr1 = ptr1->sibling; 54 } 55 } 56 } 57 return H; 58 } 59 //合併兩個二項堆 60 Node* Binomial_Heap_Union(Node* &H1, Node* &H2) { 61 Node* H = Make_Binomial_Heap(); 62 H = Binomial_Heap_Merge(H1, H2); 63 H1 = H2 = NULL; 64 if (H == NULL) return H; 65 Node* x, *pre_x, *next_x; 66 x = H; pre_x = NULL; next_x = x->sibling; 67 while (next_x != NULL) { 68 if ((x->degree != next_x->degree) || (next_x->sibling && 69 (x->degree == (next_x->sibling)->degree))) { //case1 and case 2 70 pre_x = x; x = next_x; 71 } else if (x->data <= next_x->data){ //case3 72 x->sibling = next_x->sibling; 73 Binomial_Link(next_x, x); 74 } else { //case4 75 if (pre_x == NULL) { 76 H = next_x; 77 } else { 78 pre_x->sibling = next_x; 79 } 80 Binomial_Link(x, next_x); 81 x = next_x; 82 } 83 next_x = x->sibling; 84 } 85 return H; 86 } 87 //插入新元素 88 Node* Binomial_Heap_Insert(Node* &H, int x) { 89 Node* H1 = Make_Binomial_Heap(); 90 H1 = new Node(x, 0, NULL, NULL, NULL); 91 H = Binomial_Heap_Union(H, H1); 92 return H; 93 } 94 95 96 int main() 97 { 98 Node* H = Make_Binomial_Heap(); 99 int a, n; 100 for (int i = 0; i < 10; i++) { 101 cin >> a; 102 Binomial_Heap_Insert(H, a); 103 printf("%d\n", Binomial_Heap_Minimum(H)->data); 104 } 105 cout << "insert successfully!" << endl; 106 return 0; 107 }