二项堆gydF4y2Ba
一个gydF4y2Ba二项堆gydF4y2Ba是具体实现的吗gydF4y2Ba堆gydF4y2Ba数据结构。二项堆是集合gydF4y2Ba二项树gydF4y2Ba它们连接在一起,每棵树都是一个有序堆。在二叉树堆中,有一棵二叉树或零棵二叉树gydF4y2Ba 在哪里gydF4y2Ba 帮助描述给定树的元素数量:gydF4y2Ba .二项堆类似于gydF4y2Ba二进制堆gydF4y2Ba但二项堆有一个更具体的结构,并允许高效地合并堆。堆通常用于实现gydF4y2Ba优先级队列gydF4y2Ba它们又被用于许多类型的算法的实现中,比如gydF4y2Ba最短路径查找算法gydF4y2Ba-这些快速的操作有助于使这些算法更有效。gydF4y2Ba
内容gydF4y2Ba
二项树gydF4y2Ba
二项堆是由gydF4y2Ba二项树gydF4y2Ba.gydF4y2Ba
二项树gydF4y2Ba 是由两棵二叉树组成的吗gydF4y2Ba 连接在一起,使得一个根是另一个根的最左边的子结点。gydF4y2Ba[2]gydF4y2Ba
二项式树递归定义如下:gydF4y2Ba[3]gydF4y2Ba
- 0阶的二叉树是一个单节点。gydF4y2Ba
- 一个k阶的二叉树有一个根节点,它的子节点是k - 1, k - 2,…、2,1,0(按此顺序)。gydF4y2Ba
下图是顺序为0、1、2和3的二项式树的集合(从左到右)。顺序表示根节点能够拥有多少个子节点。例如,order3节点有三个子节点,而order0节点没有子节点。gydF4y2Ba
二项树的性质gydF4y2Ba[4]gydF4y2Ba
一个订单gydF4y2Ba 二项树gydF4y2Ba 具有以下属性:gydF4y2Ba
- 这棵树的高度是gydF4y2Ba .例如,在上图中,如果树只包含0gydF4y2Ba 顺序节点,高度是gydF4y2Ba .因为整个树是有序的gydF4y2Ba ,其高度为gydF4y2Ba
- 总共有gydF4y2Ba 树中的节点。gydF4y2Ba
- 这棵树已经gydF4y2Ba 节点深度gydF4y2Ba
- 根的度是gydF4y2Ba
- 删除根产量gydF4y2Ba 二叉树:gydF4y2Ba
二项堆gydF4y2Ba
二项堆可以使用gydF4y2Ba双链表gydF4y2Ba存储根节点。每个节点存储关于父指针、左、右兄弟指针、左多数子指针、子指针的数量和键的信息。由于列表是双向链接的,父节点有指向子节点的指针,子节点有指向父节点的指针。使用双链表可以在固定时间内插入和删除根列表,将两个根列表合并在一起需要固定时间,等等。gydF4y2Ba
二项堆的结构类似于gydF4y2Ba二进制数gydF4y2Ba系统。例如,二项堆包含gydF4y2Ba 元素将包含有序的二项式树gydF4y2Ba 和gydF4y2Ba 因为把十进制的63写成二进制需要6位数字。63的二进制数是111111。gydF4y2Ba
二项堆的性质gydF4y2Ba[4]gydF4y2Ba
对于二项堆gydF4y2Ba 节点,gydF4y2Ba
- 包含最小元素的节点是任一元素的根gydF4y2Ba 或gydF4y2Ba
- 总的来说,堆有gydF4y2Ba 二叉树;gydF4y2Ba
- 堆的高度是gydF4y2Ba
二项堆必须满足gydF4y2Ba二项堆属性gydF4y2Ba.物业情况如下:gydF4y2Ba[3]gydF4y2Ba
二项堆属性gydF4y2Ba
二项最小堆中的每一棵二项树都服从gydF4y2Ba最小堆属性gydF4y2Ba(一个节点的键值大于或等于其父节点的键值),并且在二叉树Max堆中的每棵二叉树都服从gydF4y2Bamax-heap财产gydF4y2Ba(一个节点的键小于或等于其父节点的键)。gydF4y2Ba
每一阶只能有一棵或零棵二叉树。换句话说,对于每一个gydF4y2Ba ,最多有一个有序的二叉树gydF4y2Ba 在堆中。gydF4y2Ba
第一个属性确保min/max堆属性在整个堆中保持不变。gydF4y2Ba
第二个属性意味着二项堆具有gydF4y2Ba 节点最多由gydF4y2Ba 二叉树,这是二叉堆的一个性质。gydF4y2Ba[2]gydF4y2Ba为了维护此属性,可能需要在操作后合并堆。例如,如果一个操作导致两个二阶堆,则必须采取步骤来纠正这个错误,以便保持二项堆属性。gydF4y2Ba
节点的子节点在一个双链表中链接在一起。每个子节点都有一个指向其父节点的指针,而其父节点又有一个指向其中一个子节点的指针。这是上面的二项堆的样子gydF4y2Ba链表gydF4y2Ba根:gydF4y2Ba[6]gydF4y2Ba
最小功能gydF4y2Ba
下面是二项堆如何实现堆的基本功能和每个操作的时间复杂度。这些操作用最小二项堆来描述,但可以很容易地调整为最大二项堆。gydF4y2Ba
找到最小gydF4y2Ba
使用gydF4y2Bafind-mingydF4y2Ba
函数查找堆中的最小元素,并在根列表中查找最小元素。最多有gydF4y2Ba
树gydF4y2Ba
因此gydF4y2Ba
根gydF4y2Ba
所以我们来看看gydF4y2Ba
求最小元素需要的根gydF4y2Ba
时间。gydF4y2Ba
哪些节点gydF4y2Ba
find-mingydF4y2Ba
函数搜索在堆中显示在上面的部分?gydF4y2Ba它将搜索包含树的根的链表。这个列表是gydF4y2Ba .gydF4y2Ba
合并gydF4y2Ba
二项堆gydF4y2Ba合并gydF4y2Ba
函数生成一个新的堆gydF4y2Ba联盟gydF4y2Ba两个二项堆。二叉树的根节点是最小的元素。另一棵二叉树变成了新根的一个子树。比较待合并树的根节点的键值,节点就成为新树的根节点。gydF4y2Ba
例如,要合并下面的两个二项式树,请比较根节点。自gydF4y2Ba ,左边的黑树(根节点7)作为一棵子树连接到右边的灰树(根节点3)。结果是一个3阶的树。gydF4y2Ba
合并操作的运行时间为gydF4y2Ba 在哪里gydF4y2Ba 是两个堆中较大的那个堆中的节点数。gydF4y2Ba
合并二项树gydF4y2Ba
下面是描述二项式树合并操作的伪代码。gydF4y2Ba[8]gydF4y2Ba
1 2 3 4 5 5gydF4y2Ba |
|
合并二项堆gydF4y2Ba
下面是描述如何合并二项式堆的伪代码。gydF4y2Ba[8]gydF4y2Ba
1 2 3 4 5 6 7 8 9gydF4y2Ba |
|
解释了为什么gydF4y2Ba
合并gydF4y2Ba
需要gydF4y2Ba 时间。gydF4y2Ba合并gydF4y2Ba
在gydF4y2Ba 和gydF4y2Ba 遍历根的链表gydF4y2Ba 和gydF4y2Ba .让gydF4y2Ba 的节点数gydF4y2Ba 和gydF4y2Ba 的节点数gydF4y2Ba .换句话说,它至多遍历一次gydF4y2Ba 节点。gydF4y2Ba运行时间与根列表中的树的数量成正比。因此,需要gydF4y2Ba 在最坏情况下合并两个堆的时间。gydF4y2Ba[10]gydF4y2Ba
提取最小gydF4y2Ba
该操作删除二项堆中键值最小的节点。为此,该函数找到根gydF4y2Ba
与gydF4y2Bafind-mingydF4y2Ba
函数,然后删除它。这将原始堆分成两个,因此需要使用gydF4y2Ba合并gydF4y2Ba
函数。这个操作需要gydF4y2Ba
时间。gydF4y2Ba
下面是描述如何删除或提取最小元素的伪代码。gydF4y2Ba[8]gydF4y2Ba
1 2 3 4 5 6 7 8gydF4y2Ba |
|
插入gydF4y2Ba
插入gydF4y2Ba
取二项式堆gydF4y2Ba
和插入元素gydF4y2Ba
进去。它创建了一个新的堆gydF4y2Ba
和插入gydF4y2Ba
进去。然后合并gydF4y2Ba
和gydF4y2Ba
以获得最终的组合堆。gydF4y2Ba
这个操作需要gydF4y2Ba
时间,但是平摊的时间gydF4y2Ba插入gydF4y2Ba
是gydF4y2Ba
.gydF4y2Ba
删除gydF4y2Ba
把一个元素gydF4y2Ba
.如果gydF4y2Ba
在堆中,使用gydF4y2Ba降低关键gydF4y2Ba
的值gydF4y2Ba
的键指向负无穷,并使用gydF4y2Ba取出最小值gydF4y2Ba
函数。gydF4y2Ba
此操作的运行时间为gydF4y2Ba .gydF4y2Ba
降低关键gydF4y2Ba
这个函数接受一个元素gydF4y2Ba 从二项堆中减小其键值gydF4y2Ba .如果gydF4y2Ba 是二叉树吗gydF4y2Ba ,反复交换gydF4y2Ba 直到堆顺序恢复。gydF4y2Ba
此操作的运行时间为gydF4y2Ba .gydF4y2Ba
实现gydF4y2Ba
下面是二项堆的伪代码实现:gydF4y2Ba[11]gydF4y2Ba[2]gydF4y2Ba
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101gydF4y2Ba |
|
Python对二项式堆的实现要比这个伪代码长得多。可以找到一些Python实现的例子gydF4y2Ba在这里gydF4y2Ba,gydF4y2Ba在这里gydF4y2Ba,gydF4y2Ba在这里gydF4y2Ba.gydF4y2Ba
二项堆的运行时间总结gydF4y2Ba
操作gydF4y2Ba | 运行时间gydF4y2Ba |
插入gydF4y2Ba | |
删除gydF4y2Ba | |
找到最小值gydF4y2Ba | |
取出最小值gydF4y2Ba | |
降低关键gydF4y2Ba | |
合并gydF4y2Ba |
另请参阅gydF4y2Ba
参考文献gydF4y2Ba
- , L。gydF4y2Ba二项Trees.svggydF4y2Ba.2016年6月5日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Binomial_Trees.svggydF4y2Ba
- Cormen, T., Leiserson, C., Rivest, R., & Stein, C.(2001)。gydF4y2Ba算法导论(第二版)gydF4y2Ba(页455 - 475)。麻省理工学院出版社。gydF4y2Ba
- , .gydF4y2Ba二项堆gydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/Binomial_heapgydF4y2Ba
- 韦恩,K。gydF4y2Ba二项堆gydF4y2Ba.2016年6月5日,从gydF4y2Bahttps://www.cs.princeton.edu/~wayne/kleinberg-tardos/pdf/BinomialHeaps.pdfgydF4y2Ba
- D。gydF4y2Ba二项堆- 13. svggydF4y2Ba.2016年6月5日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Binomial-heap-13.svggydF4y2Ba
- 加勒,D。gydF4y2Ba二项堆,斐波那契堆gydF4y2Ba.2016年6月7日,从gydF4y2Bahttp://www.cs.usfca.edu/~galles/cs673/lecture/lecture13.printable.pdfgydF4y2Ba
- , L。gydF4y2Ba二项堆merge1.svggydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Binomial_heap_merge1.svggydF4y2Ba
- , .gydF4y2Ba二项堆gydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/Binomial_heapgydF4y2Ba
- , L。gydF4y2Ba二项堆merge2.svggydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/File:Binomial_heap_merge2.svggydF4y2Ba
- 克鲁格,R。gydF4y2Ba第二周课程总结gydF4y2Ba.2016年6月26日,从gydF4y2Bahttp://www.cs.toronto.edu/~krueger/cscB63h/lectures/lec02.txtgydF4y2Ba
- Stergiopoulos, S。gydF4y2Ba二项堆运算的算法gydF4y2Ba.2016年6月7日,从gydF4y2Bahttp://www.cse.yorku.ca/~aaw/Sotirios/BinomialHeapAlgorithm.htmlgydF4y2Ba