二项堆学习笔记(未完成)
2013-12-31 17:11 凝月流风 阅读(225) 评论(0) 编辑 收藏 举报二项堆:
1.二项堆是由一些二项树连接而成,每一棵二项树都遵循最小堆性质(即关键字的节点大于等于其父亲几点)
2.对任意的度数k,一个二项堆至多有一棵二项树的根度数为k (说明一个二项堆最多只有lgn+1棵二项树,
将n写成二进制,每一个值为1的位对应一棵二项树);
二项堆中的各二项树的根被组织成一个链表,称为根表,且各根的度数是严格递增的
操作:
1.建堆操作:Make-Heap 时间复杂度: O(1)
2.返回最小元素: Minumum lgn
过程:扫描一遍根表即可找出最小值,每棵二项树的最小值都在根节点处;
3.合并两个二项堆: Union lgn
合并过程:先将两个二项堆的二项树按度数排序连接成一个,然后从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 }