我正在Purely Functional Data Structures中阅读Binomial Heap
。
insTree
函数的实现让我非常困惑。以下是代码集
datatype Tree = Node of int * Elem.T * Tree list
fun link (t1 as Node (r, x1, c1), t2 as Node (_, x2, c2)) =
if Elem.leq (x1, x2) then Node (r+1, x1, t2::c1)
else Node (r+1, x2, t1::c2)
fun rank (Node (r, x, c)) = r
fun insTree (t, []) = [t]
| insTree (t, ts as t' :: ts') =
if rank t < rank t' then t::ts else insTree (link (t, t'), ts')
我的困惑在于insTree
中的一点为什么它不考虑等级t的情况&gt;排名t&#39; ?
在if rank t < rank t' then t::ts else insTree (link (t, t'), ts')
,
我认为inserting a binomial tree into a binomial heap
的过程应该是这样的:
rank+1
新树,然后再次尝试将新树插入堆中。所以,我认为正确的fun insTree
可能是这样的:
fun insTree (t, []) = [t]
| insTree (t, ts as t' :: ts') =
if rank t < rank t' then t::ts
else if rank t = rank t' then insTree (link (t, t'), ts')
else t'::(insTree (t, ts'))
答案 0 :(得分:1)
insTree是一个用户不可见的辅助函数。用户调用insert,后者又调用insTree和0级树,以及排名增加的树列表。 insTree具有一个不变量,即t的等级是&lt; =列表中第一棵树的等级。所以如果它不是&lt;,那么它必须是=。
你是对的,如果insTree是一个通用的公共功能,而不是一个特殊用途的私人功能,那么就必须处理丢失的情况。
答案 1 :(得分:0)
这背后的一个重要细节是二项式堆不是碰巧有k个孩子的任何树。这是一棵严格定义为
的树0阶的二叉树是单个节点,和 n阶二叉树是一个单个节点,其子序列树的顺序为0,1,2,...,n - 1作为子节点。
这个answer,解释为什么插入函数(构造二项式堆所需的函数)不管理这些情况(理论上它们不可能发生)。也许您提出的案例对合并操作有意义(但底层实现应该有所不同)。