二项队列
-
前序知识
左式堆的各种操作,斜堆的各种操作
-
二项队列概念
二项队列不是一颗堆序的数,而是堆序树的集合,成为森林。
具有的性质:
- 每一棵树都是有约束的树,叫做二项树
- 高度为k的第k个二项树Bk由一个根节点和B0, B1, …B(k-1)构成。(k从0开始)
- 高度为k的二项树的结点个数为2^k
我们可以将其理解为二进制的一个数组,从前往后看,例如1101,意义为我们有一颗高度为0的树(节点个数为20个),高度为1的树(节点个数21个),高度为3的树(节点个数2^3个)
-
二项队列的操作
- 查找最小项
- 合并两颗二项树
- 插入一颗二项树
- 删除最小
-
二项队列的代码实现
-
队列申明
typedef struct BinNode *Position; typedef struct BinNode *BinTree; typedef struct Collection *BinQueue; struct BinNode { ElementType Element;//二项树元素类型 Position LeftChild;//最左边的孩子 Position Sibling;//兄弟节点 }; struct Collection//森林申明 { int CurrentSize;//数组大小 BinTree TheTrees[MaxTree];//定义二项队列长度 }
-
合并两棵二叉树
这里对指针的大量运用,需要慢慢的理解体会
合并同样大小的两颗二项树的例程
BinTree CombineTree(BinTree T1,BinTree T2) { if(T1->Element>T2->Element) return CombineTree(T2,T1); T2->Sibling = T1->LeftChild; T1->LeftChild = T2; return T1; }
合并两个二项队列
BinQueue Merge(BinQueue H1, BinQueue H2) { BinTree T1, T2, Carry = NULL; int i,j; if(H1->CurrentSize+H2->CurrentSize>Capacity) Error("Exceed the Capacity"); H1->CurrentSize = H1->CurrentSize + H2->CurrentSize; for(i=0,j=1;j<H1->CurrentSize;i++,j*=2) { T1 = H1->TheTrees[i]; T2 = H2->TheTrees[i]; switch(!!T1+2*!!T2+4*!!Carry) { case 0: //No Trees case 1: //Only H1 break; case 2: H1->TheTrees[i] = T2; H2->TheTrees[i] = NULL; break; case 4: //Only Carry H1->TheTrees[i] = Carry; Carry = NULL; break; case 3: //T1,T2 Carry = CombineTree(T1,T2); H1->TheTrees[i] = H2->TheTrees[i] = NULL; break; case 5: Carry = CombineTree(T1,Carry); H1->TheTrees[i] = NULL; break; case 6: Carry = CombineTree(T2,Carry); H2->TheTrees[i] = NULL; break; case 7: H1->TheTrees[i] = Carry; Carry = CombineTree(T1,T2); H2->TheTrees[i] = NULL; break; } } return H1; }
switch语句真的牛逼,这一段我看了半天才搞明白到底是怎么一回事!!!建议细细品味
删除最小值
ElementType DeleteMin(BinQueue H) { int i,j; int MinTree; BinQueue DeleteQueue; Position DeletedTree, OldRoot; ElementType MinItem; if(IsEmpty(H)) { Error("Empty BinQueue!!"); return -Infinity; } //find the minmum Min = Infinity; for(i=0;i<MaxTree;i++) { if(H->TheTrees[i] && H->TheTrees[i]->Element<MinItem) { // Updata the minmun MiniItem = H->TheTrees[i]->Element; MinTree = i; } } // have found the DeleteTree DeleteTree = H->TheTrees[MinTree]; OldRoot = DeleteTree; DeleteTree = OldRoot->LeftChild; free(OldRoot); // form the DeleteQueue DeletedQueue = Initialize(); DeletedQueue->CurrentSize = (1<<MinTree) - 1; for(j=MinTree-1;j>=0;j--) { DeletedQueue->TheTree[j] = DeletedTree; DeletedTree = DeletedTree->Sibling; DeletedQueue->TheTree[j]->Sibling = NULL; } H->TheTrees[MiniTree] = NULL; H->CurrentSize -= DeletedQueue->CurrentSize+1; Merge(H,DeletedQueue); return MinItem; }
-
参考资料:《数据结构与算法分析》以及b站视频[]: https://www.bilibili.com/video/BV1fC4y1h7CT?spm_id_from=333.337.search-card.all.click