用循环不变式证明BINOMIAL-HEAP-UNION(H1, H2)的正确性

来源:互联网 发布:老凤祥黄金换购的算法 编辑:程序博客网 时间:2024/05/21 00:56

初始化:x指向Head[H]Head[H]是对两个二项堆的根表合并后的数据结构的第一个结点(合并时根表的度数是按照单调递增排列的),并且Head[H]不为NILnext-x指向x的兄弟结点。x指向的结点左侧(包括结点本身)所构成的数据结构是二项堆,因为此时该堆只有一个以Head[H]为根结点的二项树。

 

保持:需要分成四种情况讨论。

首先,循环的目的是要把x沿着根表向链表的尾端推进,并且在循环过程中保持x结点左边的数据结构(包括x结点,以及以x结点为根的二项树)是二项堆。

 

情况1):degree[x] degree[next-x]

这种情况最简单,因为根表本身是按照度数单调递增排列的,因此degree[next-x]>degree[x],把x的指针向右推进一个兄弟结点,显然可以保证:

x结点左边的数据结构(包括x结点,以及以x结点为根的二项树)是二项堆。

 

情况2):sibling[next-x] NIL and degree[sibling[next-x]] = degree[x]

这种情况意味着,xx的兄弟结点和x的兄弟的兄弟结点的度数相同(最多有3个相邻的结点度数相同,否则合并前就不是二项堆了)

这时,将x的指针向右推进一个兄弟结点,会破坏x结点左边的数据结构(包括x结点,以及以x结点为根的二项树)是二项堆的性质,但因为这种情况下不会退出循环,实际这样做会把问题转换到情况3)或4)。

 

情况3):当xx的兄弟的度数相等,但和x的兄弟的兄弟的度数不同,并且key[x] key[next-x]

因为度数相同,因此要对这两个二项树进行连接。把x的兄弟结点为根的二项树与x结点为根的二项树进行连接,保证x是连接后的总体二项树的根(用x做根,保证最小堆)。

这时,x结点左边的数据结构(包括x结点,以及以x结点为根的二项树)是二项堆。

 

情况4):当xx的兄弟的度数相等,但和x的兄弟的兄弟的度数不同,并且key[x] > key[next-x]

如果x的上一个结点是NIL,意味着x是指向的head[H],这时需要把head[H]改一下,让它指向x的兄弟结点。如果x的上一个结点不是NIL,那么需要修改prev-x的指针指向x的兄弟结点(因为x结点代表的子树需要被连接)。

然后对x为根和x的兄弟为根的二项树进行连接,这次连接后的根是x的兄弟结点(为保证最小堆性质)。最后,将x指向x的兄弟结点。

此时,x结点左边的数据结构(包括x结点,以及以x结点为根的二项树)是二项堆。

 

终止:当循环结束时,x的兄弟结点为NILx已经指向根表的尾端。意味着x结点左边的数据结构(包括x结点,以及以x结点为根的二项树)已经包括了合并堆的所有结点。并且,该数据结构就是一个二项堆。所以,合并算法是正确的。

 

二项堆的合并1

 

二项堆的合并2

原创粉丝点击