将字母插入空堆
Inserting letters onto an empty heap
我正在尝试将 "KONTINUASJONSEKSAMEN" 插入到空堆中。结果应该会产生 "USTSOSNOMNJNNEKAAKEI",但我做不到。我最终得到 "UTSSOONSMNJNNEKAAKEI",这是我从下面的可视化中计算出来的。
U
/ \
T S
/ \ / \
S O O N
/ \ / \ / \ / \
S M N J N N E K
/ \ /\ /
A A K E I
我从顶部的第一个 K 开始,向下,从左到右处理单词的其余部分,在较低值 parents 和较高值 children 之间切换。其中较高的值意味着更接近 Z。
你知道我错在哪里了吗?
我认为问题在于您是自上而下进行插入,而该堆是通过自下而上进行插入而构建的。我使用了自己的堆实现来执行自下而上的插入,并且从该输入字符串产生的堆正是您预期的输出。
如果你是在二叉堆中做自上而下的插入,那么遇到这种情况就会产生歧义:
K
S S
A B C D
也就是说,您要插入的节点小于它的两个子节点,并且两个子节点相等。
你选择和哪个 'S' 交换?如果你总是选择左边的那个,而其他人总是选择右边的那个,那么最终的堆可能会大不相同。例如:
S S
K S S K
A B C D A B C D
两者都是有效的堆。
通常,堆插入是通过将新节点添加为堆的最后一个节点,然后将其冒泡到树中的适当位置来完成的。因此,如果您从根部的 K 开始并添加 O,则您有:
K
O
你注意到 O 大于 K,所以你交换节点得到:
O
K
然后你加上N得到
O
K N
你先把 T 添加为堆的最后一个节点,然后冒泡起来:
O
K N
T
T 大于 K,因此交换节点:
O
T N
K
并且 T 大于 O,所以你交换它们:
T
O N
K
这样自底向上插入,没有歧义
您还应注意,自下而上插入比自上而下插入更有效。如果在顶部插入,那么它 always 需要 log2(n) 次迭代,其中 n 是堆中当前的项目数。即使新项替换了根,您也必须筛选直到在叶级有一个新条目。
当您通过首先将新节点放在叶级别来进行自底向上插入时,有一半的时间节点将留在叶级别。并且 75% 的时间节点不会上升超过一级。唯一需要进行 log2(n) 交换的时间是新项替换根项时。有一个很好的论据可以证明二叉堆插入是 O(1),但假设是自下而上的插入。有关详细信息,请参阅 。
有关如何实现自下而上插入的更多信息,请参阅我在 http://blog.mischel.com/2013/09/29/a-better-way-to-do-it-the-heap/ 上关于堆的博客系列。
我找到了一个快速的方法。我没有用树叶打字和擦除无尽的树,而是将字符设置在一个数组中,为每个 1st、2nd、4th、8th、16...字符画一条线。求助热线左侧的字符是求助热线右侧相邻字符的 parent(s)。字符1是parent到2和3。字符2是parent到4和5等等。我再次测试左 child 是否大于 parent,如果是则它们切换(注意我的 workbook/excel 文档中的切换直接在前一个 parent/child 之下)。然后我检查了右边的 child 和(新的)parent。附上我的 excel 文档的屏幕截图。
我正在尝试将 "KONTINUASJONSEKSAMEN" 插入到空堆中。结果应该会产生 "USTSOSNOMNJNNEKAAKEI",但我做不到。我最终得到 "UTSSOONSMNJNNEKAAKEI",这是我从下面的可视化中计算出来的。
U
/ \
T S
/ \ / \
S O O N
/ \ / \ / \ / \
S M N J N N E K
/ \ /\ /
A A K E I
我从顶部的第一个 K 开始,向下,从左到右处理单词的其余部分,在较低值 parents 和较高值 children 之间切换。其中较高的值意味着更接近 Z。
你知道我错在哪里了吗?
我认为问题在于您是自上而下进行插入,而该堆是通过自下而上进行插入而构建的。我使用了自己的堆实现来执行自下而上的插入,并且从该输入字符串产生的堆正是您预期的输出。
如果你是在二叉堆中做自上而下的插入,那么遇到这种情况就会产生歧义:
K
S S
A B C D
也就是说,您要插入的节点小于它的两个子节点,并且两个子节点相等。
你选择和哪个 'S' 交换?如果你总是选择左边的那个,而其他人总是选择右边的那个,那么最终的堆可能会大不相同。例如:
S S
K S S K
A B C D A B C D
两者都是有效的堆。
通常,堆插入是通过将新节点添加为堆的最后一个节点,然后将其冒泡到树中的适当位置来完成的。因此,如果您从根部的 K 开始并添加 O,则您有:
K
O
你注意到 O 大于 K,所以你交换节点得到:
O
K
然后你加上N得到
O
K N
你先把 T 添加为堆的最后一个节点,然后冒泡起来:
O
K N
T
T 大于 K,因此交换节点:
O
T N
K
并且 T 大于 O,所以你交换它们:
T
O N
K
这样自底向上插入,没有歧义
您还应注意,自下而上插入比自上而下插入更有效。如果在顶部插入,那么它 always 需要 log2(n) 次迭代,其中 n 是堆中当前的项目数。即使新项替换了根,您也必须筛选直到在叶级有一个新条目。
当您通过首先将新节点放在叶级别来进行自底向上插入时,有一半的时间节点将留在叶级别。并且 75% 的时间节点不会上升超过一级。唯一需要进行 log2(n) 交换的时间是新项替换根项时。有一个很好的论据可以证明二叉堆插入是 O(1),但假设是自下而上的插入。有关详细信息,请参阅
有关如何实现自下而上插入的更多信息,请参阅我在 http://blog.mischel.com/2013/09/29/a-better-way-to-do-it-the-heap/ 上关于堆的博客系列。
我找到了一个快速的方法。我没有用树叶打字和擦除无尽的树,而是将字符设置在一个数组中,为每个 1st、2nd、4th、8th、16...字符画一条线。求助热线左侧的字符是求助热线右侧相邻字符的 parent(s)。字符1是parent到2和3。字符2是parent到4和5等等。我再次测试左 child 是否大于 parent,如果是则它们切换(注意我的 workbook/excel 文档中的切换直接在前一个 parent/child 之下)。然后我检查了右边的 child 和(新的)parent。附上我的 excel 文档的屏幕截图。