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

二项树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 }


 

 


作者:​​xingoo​