为什么我们从下向上而不是从上到下构建最大堆
Why we build max heap from bottom up instead from top bottom
问题:为什么我们要BUILD-MAX-HEAP第2行的循环索引i
从⌊length[A]/2⌋
减少到1
而不是从 1
增加到 ⌊length[A]/2⌋
?
算法:(算法导论书提供):
我试着用下面的图来展示这个。
方法 1:如果我们以相反的方式应用构建堆,从数组 A = <5,3,17,10,84>
的 1
到 ⌊length[A]/2⌋
,我们将有:
方法 2:如果我们以与 ⌊length[A]/2⌋
相反的方式应用构建堆并减少到数组 A = <5,3,17,10,84>
的 1
,我们将有:
问题:我看到在这两种情况下,父项大于其子项的堆 属性 得到维护,所以我不明白为什么解决方案说会出现这样的问题,“我们将不允许调用 MAX-HEAPIFY,因为它会使子树成为最大堆的条件失败。也就是说,如果我们从 1
开始,则无法保证 A[2]
和 A[3]
是最大堆的根。“
当以 i 为根的子树服从堆 属性 到处 除了 可能是根值(在 i)本身,这可能需要筛选。 MAX_HEAPIFY
的工作只是将根的值移动到正确的位置。它无法修复堆的任何其他违规行为 属性。但是,如果保证 i 下面的树的其余部分服从堆 属性,那么你可以确定 i[ 的子树=43=] 将在 MAX_HEAPIFY
具有 运行.
之后成为一个堆
所以如果你从顶部节点开始,那么谁知道你会得到什么......树的其余部分预计不会服从堆 属性,所以 MAX_HEAPIFY
不会(必然)交付一堆。以自上而下的方式继续工作也无济于事。
如果我们采用示例树并执行 forward 循环替代方案,那么我们从调用此树上的 MAX_HEAPIFY(1)
开始:
5
/ \
3 17
/ \
10 84
...然后 5 将与 17 交换(在位置 3),然后我们将在该节点上递归调用 MAX_HEAPIFY(3)
,这什么都不做。所以我们会得到:
17
/ \
3 5
/ \
10 84
接下来,我们调用 MAX_HEAPIFY(2)
将 3 与 84 交换:
17
/ \
84 5
/ \
10 3
再次对值为 3 的节点进行递归调用,但这不会执行任何操作。
这是 forward 循环替代中 MAX_HEAPIFY
的最后一次调用...我们可以看到值 84 没有机会找到所有路径通往它所属的顶部的方式。
问题:为什么我们要BUILD-MAX-HEAP第2行的循环索引i
从⌊length[A]/2⌋
减少到1
而不是从 1
增加到 ⌊length[A]/2⌋
?
算法:(算法导论书提供):
我试着用下面的图来展示这个。
方法 1:如果我们以相反的方式应用构建堆,从数组 A = <5,3,17,10,84>
的 1
到 ⌊length[A]/2⌋
,我们将有:
方法 2:如果我们以与 ⌊length[A]/2⌋
相反的方式应用构建堆并减少到数组 A = <5,3,17,10,84>
的 1
,我们将有:
问题:我看到在这两种情况下,父项大于其子项的堆 属性 得到维护,所以我不明白为什么解决方案说会出现这样的问题,“我们将不允许调用 MAX-HEAPIFY,因为它会使子树成为最大堆的条件失败。也就是说,如果我们从 1
开始,则无法保证 A[2]
和 A[3]
是最大堆的根。“
当以 i 为根的子树服从堆 属性 到处 除了 可能是根值(在 i)本身,这可能需要筛选。 MAX_HEAPIFY
的工作只是将根的值移动到正确的位置。它无法修复堆的任何其他违规行为 属性。但是,如果保证 i 下面的树的其余部分服从堆 属性,那么你可以确定 i[ 的子树=43=] 将在 MAX_HEAPIFY
具有 运行.
所以如果你从顶部节点开始,那么谁知道你会得到什么......树的其余部分预计不会服从堆 属性,所以 MAX_HEAPIFY
不会(必然)交付一堆。以自上而下的方式继续工作也无济于事。
如果我们采用示例树并执行 forward 循环替代方案,那么我们从调用此树上的 MAX_HEAPIFY(1)
开始:
5
/ \
3 17
/ \
10 84
...然后 5 将与 17 交换(在位置 3),然后我们将在该节点上递归调用 MAX_HEAPIFY(3)
,这什么都不做。所以我们会得到:
17
/ \
3 5
/ \
10 84
接下来,我们调用 MAX_HEAPIFY(2)
将 3 与 84 交换:
17
/ \
84 5
/ \
10 3
再次对值为 3 的节点进行递归调用,但这不会执行任何操作。
这是 forward 循环替代中 MAX_HEAPIFY
的最后一次调用...我们可以看到值 84 没有机会找到所有路径通往它所属的顶部的方式。