前言:
这次,将进行介绍的是一个特殊而有趣的队列——二项队列。在二项队列中你会发现人们是怎么把二进制的思想体现在数据结构中的;同时二项队列也是一种很高效的队列,对于合并、插入以及DeleteMin操作,它的最坏运行时间为O(LogN),而插入平均花费常数时间进行。那么接下来开始我们的讲解吧~~
原理:
首先我们得知道,二项队列并不是一颗堆序的树,而是堆序树的一个集合,也可以成为
森林。而在森林中的每棵树,我们称之为
二项树。二项树有如下的性质:
1. 高度为0的二项树是一颗单节点的树;
2. 高度为n的二项树Bn,通过将一颗二项树B(n-1)接到另一颗二项树B(n-1)上构成;
换句话来将,对于高度为n的树它的节点数为2的n次方;

如上图所示,这就是二项树深林,而二项队列与普通的堆相同,都支持合并,插入以及DeleteMin操作;
表现方式:
对于二项树,我们不使用一般的树的形式来对其进行储存,我们要求二项树的每一个节点包含数据,第一个儿子以及其右兄弟,同时保证其子节点元素一定小于父节点的元素。在离散数学中,这是一种很普遍的表达树的形式。

合并:
对于二项队列来说合并可以说是最重要的操作,合并的目的是将两个二项队列进行合并,其中涉及到了单独两科二项树之间的合并以及森林(二项队列)之间的合并;对于二项树之间的合并是非常简单的,即先判断两颗二项树的头结点的大小,将元素较大的作为另外一颗树的新儿子,旧儿子则变为新儿子的右兄弟。

代码如下:
BinTree B_queue::CombineTrees(BinTree T1, BinTree T2) {
// 判断是否需要反接
if (T1->Element > T2->Element)
return CombineTrees(T2, T1);
// 将T2接在T1上
T2->NextSibling = T1->LeftChild;
T1->LeftChild = T2;
return T1;
}
可以看到合并两颗二项树所需要的操作是非常少的。那么如何进行森林的合并呢?这里,我们需要一点二进制的思想。我们先回忆一下,两个二进制数相加的情况:比如00101+00011的结果用二进制表示将会是01000,我们将从最低位开始运算,满二进一并向高位进位。而在二项树的合并中,我们也保留相同的思路,将有树看为1将没有树看为0,那么从高度最小的二项树之间开始合并,树的合并也就等效成了二进制的加法。
上图

我们可以发现上图中的二项队列合并可以看做二进制的加法0011 + 0111 = 1010;也就是说,
我们运用二进制的思想,就可以很好的解决二项队列的合并问题!