斜堆这种数据结构是在Weiss《数学结构与算法分析》的书里看到的,实际上它作为一种接近左式堆的数据结构,在递归合并时无条件进行左右子堆交换,减少左子堆NPl与右子堆NPl的比较判断。但是,这样的简略处理使斜堆的右路径可能很长,在合并递归时导致栈溢出,所以感觉斜堆本身并不是一个特别好用的结构。也许正是因为如此,许多地方对斜堆的描述都甚少,Weiss只给了一个斜堆的递归定义,找过各种百科和博客找了一圈也没有发现讨论斜堆非递归定义的内容,于是花时间想了一下并且写了个证明,实际使用意义也许并不大,但是大致可以作为一种思维训练,具体内容如下:
已知条件(斜堆的递归定义):
a、只有一个结点的堆是斜堆
b、两斜堆按【斜堆合并法】合并后的堆是斜堆
c、斜堆合并法(递归)的步骤:
步骤①:如其中一斜堆为空,则返回另一斜堆
步骤②:如两斜堆均不为空,则将根节点值较小(根据对称性,不妨设其为小顶堆)的斜堆与根结点值较大的斜堆的右子堆以【斜堆合并法】合并,作为新的右子堆。合并完成后,交换所得堆的左右子堆。
求并证明:斜堆的非递归定义
证明:
先给出结论——斜堆即,除了叶结点以外,其它所有结点都有左子堆的大顶堆或小顶堆。
证明充分性——
如对于任意两个堆(是否斜堆都无所谓)进行【斜堆合并法】例程,由于步骤②,堆A先与堆B的右子堆合并作为新的右子堆,并且交换新堆B的左右子堆,显而易见地,合并后所得堆的左子堆必不为空。
由于斜堆属于任意堆,故任意两个斜堆进行【斜堆合并法】后,其左子堆必不为空。同时根据递归定义,此时合并所得的堆是斜堆。因此,所有的斜堆都是除了叶结点以外,其它所有结点都有左子堆的大顶堆或者小顶堆。
充分性得证。
证明必要性——
反证法,假设存在某个高度为h的大顶或小顶堆H,它满足【除了除了叶结点以外,其它所有结点都有左子堆】这一条件,并且它不是斜堆。以下试图推出矛盾。
根据斜堆的定义,类似左式堆的【左式堆的左右子堆都是左式堆】,易知斜堆的左右子堆都是斜堆。根据逆反命题,仅当堆的左右子堆至少有一个不是斜堆时,该堆不是斜堆。
那么对于此前假设的堆H,其左子堆与右子堆必有其一不是斜堆。即必有一高度为h-k(1≤k≤h-1)的子堆,满足【除了除了叶结点以外,其它所有结点都有左子堆】这一条件,并且它不是斜堆。
依次类推,多次循环后,可得,在堆H中,至少有一高度为1的子堆,它不是斜堆,且满足【除了除了叶结点以外,其它所有结点都有左子堆】。
但是,对于高度为1且满足条件的堆,仅两种情况(一种有三结点即根+左右结点,一种有二结点即根+左结点),此两种堆都为斜堆,所以产生矛盾,假设不成立。
所以,所有满足【除了除了叶结点以外,其它所有结点都有左子堆】的大顶堆或者小顶堆,都是斜堆。
必要性得证。
至此证明完毕,最后再重复一下对斜堆的非递归定义吧:
斜堆是除了叶结点以外其它所有结点都有左子堆的大顶堆或小顶堆。