堆的树结构是什么?

时间:2015-01-11 16:46:31

标签: c++ heap

我正在阅读Nicolai M. Josuttis" C ++标准库,教程和参考",ed2。

他解释了堆数据结构和相关的STL函数(第607页):

  

该程序具有以下输出:

on entry: 3 4 5 6 7 5 6 7 8 9 1 2 3 4
after make_heap(): 9 8 6 7 7 5 5 3 6 4 1 2 3 4
after pop_heap(): 8 7 6 7 4 5 5 3 6 4 1 2 3
after push_heap(): 17 7 8 7 4 5 6 3 6 4 1 2 3 5
after sort_heap(): 1 2 3 3 4 4 5 5 6 6 7 7 8 17

enter image description here

我想知道如何解决这个问题?例如,为什么叶子" 4"在路径9-6-5-4下是节点" 5"的左侧子节点,而不是右侧节点的子节点?在pop_heap树结构之后呢?在IDE调试模式中,我只能看到向量的内容,有没有办法找出树结构?

2 个答案:

答案 0 :(得分:1)

向量中的第一个元素是索引0处的根。它的左子节点位于索引1处,右侧子节点位于索引2处。通常:left_child(i) = 2 * i + 1right_child(i) = 2 * i + 2以及{{1} }

考虑它的另一种方法是堆填充树中从从左到右的每个级别。在向量中的元素之后,第一级是9(1值),第二级是8 6(2个值),第三级是7 7 5 5(4个值),依此类推。这两种方法都可以帮助您在给定向量时在树结构中绘制堆。

答案 1 :(得分:1)

  为什么叶子" 4"在路径9-6-5-4下是节点" 5"的左侧子节点,而不是右侧节点的子节点?

因为如果它在右侧,那就意味着底层向量中存在间隙。树结构仅用于说明目的。它不代表堆的实际存储方式。树结构通过简单的数学公式映射到底层矢量。

树的根节点是向量的第一个元素(索引0)。节点的左子节点的索引是通过简单公式i * 2 + 1从其父节点索引获得的。并且正确孩子的索引是通过i * 2 + 2获得的。

  

然后在pop_heap之后是什么树结构呢?

根节点与其两个子节点中的较大节点 1 交换,并重复此节点直到它位于树的底部。然后它与最后一个元素交换。然后,如果必要的话,通过与其父项交换(如果它更大),将该元素向上推

根节点与堆的最后一个元素交换。然后,通过与其两个子项 1 中的较大者交换,将该元素向下推到堆中。重复这一过程,直到它处于正确的位置(即它不小于其任何一个孩子)。

所以在pop_heap之后,你的树看起来像这样:

     ----- 8 -----
     |           |
  ---7---     ---6---
  |     |     |     |
 -7-   -4-   -5-   x5
 | |   | |   | |   x
 3 6   4 1   2 3   9

9实际上不再是堆的一部分,但它仍然是向量的一部分,直到你通过调用pop_back或类似的方式擦除它。

<子> 1。如果孩子们是平等的,就像在你的例子中树的相邻7的情况一样,它可以是任何一种方式。我相信std::pop_heap将其发送到右侧,但我不确定这是否是实施定义