二项队列

二项队列是 堆序 的集合,也叫 森林。其中每一种形式都有约束。

二项树Bk由一个带有儿子的B0,B1,B2...组成,高度为k的二项树 恰好有2^k个结点。每一种高度只能出现一次...因此,只有1,2,4,8...等结点数目的二项树

deleteMin操作需要快速的找出跟的所有子树的能力,因此需要一般树的表示方法:

每个结点的儿子都在一个链表中,而且每个结点都有一个指向它的第一个儿子的指针。

二项树的每一个结点包括:数据第一个儿子,以及右兄弟

下面是二项队列类构架及结点定义:

复制代码
 1 template <typename Comparable>
 2 class BinomialQueue
 3 {
 4 public:
 5     BinomialQueue();
 6     BinomialQueue(const Comparable & item);
 7     BinomialQueue(const BinomialQueue & rhs);
 8     ~BinomialQueue();
 9 
10     bool isEmpty() const;
11     const Comparable & findMin() const;
12 
13     void insert(const Comparable & x);
14     void deleteMin();
15     void deleteMin(Comparable & minItem);
16 
17     void makeEmpty();
18     void merge(BinomialQueue & rhs);
19 
20     const BinomialQueue & operator=(const BinomialQueue & rhs);
21 private:
22     struct BinomialNode
23     {
24         Comparable element;
25         BinomiaNode *leftChild;
26         BinomialNode *nextSibling;
27 
28         BinomialNode(const Comparable & theElement,BinomialNode *lt,BinomialNode *rt)
29             :element(theElement),leftChild(lt),rightChild(rt)
30         {
31         }
32     };
33     
34     enum{DEFAULT_TREES = 1};
35 
36     int currentSize;
37     vector<BinomialNode *> const;
38     int capacity() const;
39     BinomialNode * combineTrees(BinomialNode *t1,BinomialNode *t2);
40     void makeEmpty(BinomialNode * & t);
41     BinomialNode * clone(BinomialNode *t) const;
42 };
复制代码

合并同样大小的两棵树二项树的例程:

复制代码
1 BinomialNode * combineTrees(BinomialNode *t1,BinomialNode *t2)
2 {
3     if(t2->element < t1->element)
4         return combineTrees(t2,t1);
5     t1->nextSibling = t1->leftChild;
6     t1->leftChild = t2;
7     return t1;
8 }
复制代码

合并两个优先队列的例程:

复制代码
 1 void merge(BinomialQueue & rhs)
 2 {
 3     if(this==&rhs)
 4         return;
 5     currentSize += rhs.currentSize;
 6     if(currentSize > capacity())
 7     {
 8         int oldNumTrees = theTrees.size();
 9         int newNumTrees = max(theTrees.size(),rhs.theTrees.size())+1;
10         theTrees.resize(newNumTrees);
11         for(int i = oldNumTrees; i<newNumTrees; i++)
12             theTrees[i] = NULL;
13     }
14     BinomialNode *carry = NULL;
15     for(int i=0,j=1; j<=currentSize; i++,j*=2)
16     {
17             BinomialNode *t1 = theTrees[i];
18             BinomialNode *t2 = i < rhs.theTrees.size()? rhs.theTrees[i]:NULL;
19 
20             int whichCase = t1 == NULL ? 0 : 1;
21             whichCase += t2 == NULL? 0 : 2;
22             whichCase += carry == NULL? 0 : 4;
23 
24             switch(whichCase)
25             {
26                 case 0:
27                 case 1:
28                     break;
29                 case 2:
30                     theTrees[i] = t2;
31                     rhs.theTrees[i] = NULL;
32                     break;
33                 case 4:
34                     theTrees[i] = carry;
35                     carry = NULL;
36                     break;
37                 case 3:
38                     carry = combineTrees(t1,t2);
39                     theTrees[i] = rhs.theTrees[i] = NULL;
40                     break;
41                 case 5:
42                     carry = combineTrees(t1,carry);
43                     theTrees[i] = NULL;
44                     break;
45                 case 6:
46                     carry = combineTrees(t2,carry);
47                     rhs.theTrees[i] = NULL;
48                     break;
49                 case 7:
50                     theTrees[i] = carry;
51                     carry = combineTrees(t1,t2);
52                     rhs.theTrees[i] = NULL;
53                     break;
54             }
55     }
56     for(int k = 0; k < rhs.theTrees.size(); k++)
57         rhs.theTrees[k] = NULL;
58     rhs.currentSize = 0;
59 }
复制代码

 deleteMin程序:

复制代码
 1 void deleteMin(Comparable & minItem)
 2 {
 3     if(isEmpty())
 4         throw UnderflowException();
 5     int minIndex = findMinIndex();
 6     minItem = theTrees[minIndex]->element;
 7 
 8     BinomialNode *oldRoot = theTrees[minIndex];
 9     BinomialNode *deletedTree = oldRoot->leftChild;
10     delete oldRoot;
11 
12     BinomialQueue deletedQueue;
13     deletedQueue.theTrees.resize(minIndex+1);
14     deletedQueue.currentSize = (1<<minIndex)-1;
15     for(int j = minIndex -1 ;j >= 0 ; j--)
16     {
17         deletedQueue.theTrees[ j ] = deletedTree;
18         deletedTree = deletedTree->nextSibling;
19         deletedQueue.theTrees[ j ]->nextSibling = NULL;
20     }
21 
22     theTrees[minIndex] = NULL;
23     currentSize -= deletedQueue.currentSize + 1;
24 
25     merge(deletedQueue);
26 } 
27 int findMinIndex() const
28 {
29     int i;
30     int minIndex;
31 
32     for( i = 0; theTrees[i] === NULL;i++)
33         ;
34     for(minIndex = i; i < theTrees.size();i++)
35         if(theTrees[i] != NULL && theTrees[i]->element < theTrees[minIndex]->element)
36             minIndex = i;
37 
38     return minIndex;
39 }
复制代码

 

 

转载于:https://www.cnblogs.com/luozhijun/p/6880451.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值