堆与二叉树 - 如何实现?

时间:2010-01-08 13:34:04

标签: arrays data-structures pointers heap binary-tree

在实现堆结构时,我们可以将数据存储在一个数组中,使得位置i的节点的子节点位于位置2i和2i + 1。

我的问题是,为什么我们不使用数组来表示二进制搜索树,而是处理指针等。?

感谢

7 个答案:

答案 0 :(得分:7)

如果所有子节点的位置都是静态预先计算的,那么数组本质上代表一个完全完整,完全平衡的二叉树。

并非所有“现实生活中”的二叉树都完全饱满且完美平衡。如果您碰巧有一些特别长的分支,那么您必须使整个阵列更大,以容纳最底层的所有节点。

  • 如果数组绑定的二叉树基本上是空的,则大部分数组空间都被浪费了。

  • 如果只有一些树枝的深度足以到达阵列的“底部”,那么浪费的空间也很大。

  • 如果树(或只有一个分支)需要比数组允许的“更深”增长,这将需要“增长”数组,这通常实现为复制到更大的数组。这是一项耗时的操作。

所以:使用指针可以让我们动态灵活地扩展结构。在数组中表示树是一个很好的学术练习,适用于小而简单的情况但通常不能满足“真实”计算的需求。

答案 1 :(得分:7)

个人

  1. 因为使用指针更容易 增加数据结构大小 动态

  2. 我发现维护bin更容易 树而不是堆

  3. 平衡,移除,插入树中元素的算法只会改变指针而不会像在矢量中那样物理移动。

  4. 依旧......

答案 2 :(得分:6)

主要是因为递归树允许非常简单的代码。如果将树压平成一个数组,代码变得非常复杂,因为你必须做很多簿记,递归算法会为你做。

此外,高度为N的树可以在N和2^(N+1)-1个节点之间有任何内容(。只有实际节点需要内存。如果使用数组,则必须始终为所有节点分配空间(即使是空的)除非你使用稀疏数组(这将使代码更复杂)。所以虽然很容易在内存中保持高度为100的稀疏树,但找到一台可以分配20282409603651670423947251286008字节RAM的计算机会有问题

答案 3 :(得分:2)

要将元素插入堆中,可以将其放在任何位置并与其父项交换,直到堆约束再次有效。 Swap-with-parent是一种保持堆的二叉树结构完整的操作。这意味着大小为N的堆将表示为N-cell数组,您可以在对数时间内添加新元素。

二进制搜索树可以表示为大小为N的数组,使用与堆相同的表示结构(子项2n和2n + 1),但以这种方式插入元素要困难得多,因为与堆约束不同,二叉搜索树约束要求执行旋转以检索平衡树。因此,要么设法将N节点树保存在N单元阵列中,其成本高于对数,要么通过将树保持在一个更大的数组中来浪费空间(如果我的内存服务,则可以使用红背树)浪费多达你阵列的50%)。

因此,如果内部数据是常量,则数组中的二叉搜索树才有意义。如果是,那么你不需要堆结构(子2n和2n + 1):你可以对数组进行排序并使用binary search

答案 4 :(得分:0)

据我所知,我们可以使用Array来表示二叉搜索树。 但使用指针更灵活。

答案 5 :(得分:0)

如果您需要在图算法中用作优先级队列的堆,则基于数组的实现非常有用。在这种情况下,堆中的元素是常量,您弹出最顶层的元素并插入新元素。删除顶部元素(或min元素)需要一些重新平衡才能再次成为堆,这可以使阵列合理平衡。

对此的参考是Goldberg和Tarjan关于在有向图中有效计算最优网络流的算法,iirc。

答案 6 :(得分:0)

堆数据结构是一个完整的二进制树,与BST不同。因此,对于BST,使用数组没有多大用处。