代码改变世界

二项堆学习笔记(未完成)

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 }