当前位置: 首页 > 知识库问答 >
问题:

根在arr[0]的二进制堆有什么好处

佘茂才
2023-03-14

我正在一个数组< code>arr上写一个二进制堆。

除了叶节点,每个节点都有两个子节点。

根可以位于 arr[0]arr[1]。

公认的答案是为什么在数组实现的堆中索引0未使用?说arr[1]更快。

但是答案下面的一条评论说大多数实现都将root放在arr[0]

将根放在 arr[0] 有什么好处?

共有1个答案

娄森
2023-03-14

我是回答您链接的问题的人。

在一种具有基于0的数组的语言中创建一个根在< code>arr[1]的二进制堆是愚蠢的。不是因为它浪费了微不足道的空间,而是因为它创建了毫无益处的不必要的混乱代码。

为什么代码令人困惑?因为它打破了我们作为程序员多年来一直遵循的基本规则:数组从0开始。如果你想要一个包含100个项目的数组,你可以这样声明:

int a[100];

除了二进制堆。因为一些在1973年将原始二进制堆代码从Algol(其数组是基于1的)转换为C(基于0的数组)的白痴没有改变子和父计算的头脑,我们已经结束了这个特例,在这里保存100个项目,您必须分配101:

int a[101];

当有人打电话给那个人关于不一致时,他想出了一个似是而非的表演论点。

是的,代码中有一个额外的增量指令用于计算左子索引,当计算孩子的父索引时,有一个额外的减量指令。在二进制堆所做的更广泛的上下文中,这两条指令对任何使用堆的程序的运行时间都没有实际影响。没有。如果差异甚至是可测量的,它肯定会很吵。您的计算机上发生了许多其他事情,这些事情会对您的程序性能产生更大的影响。

如果你正在编写一个需要高性能优先级队列的程序,你首先用二进制堆做什么?如果你真的要在优先级队列中存储大量的东西,你可能应该使用像配对堆这样的东西,它将优于二进制堆,尽管内存成本更高。

C STL<code>priority_queue</code>、Java<code>PriorityQueue</code>和python的heapq都使用基于0的二进制堆。编写这些包的人了解性能考虑因素。如果使用基于1的二进制堆可以显著提高性能,那么他们会这样做。他们使用基于0的堆应该告诉你,从基于1的堆中获得的任何性能都是虚幻的。

请参阅 http://blog.mischel.com/2016/09/19/but - 这就是我们总是做的方式 - 对于更完整的讨论。

 类似资料:
  • 我读了一些关于二进制堆/优先级队列的内容,并决定尝试自己实现一个。我不是最有经验的程序员,如果你们能看看我的堆类并告诉我它是否是一个好的实现,我将不胜感激。 我可以在这里改进什么?欢迎任何反馈。

  • 堆属性说: 如果A是B的父节点,则节点A的键相对于节点B的键进行排序,并在堆中应用相同的排序。要么父节点的键总是大于或等于子节点的键,最高键在根节点(这种堆称为最大堆),要么父节点的键小于或等于子节点的键,最低键在根节点(最小堆)。 但是为什么在这个wiki中,二进制堆必须是一个完整的二叉树呢?在我的印象中,堆属性并不意味着这一点。

  • 问题内容: 是否有任何特殊原因为什么不包括这种文字,而允许使用十六进制和八进制格式? 问题答案: Java 7包括它。检查新功能。 例:

  • 当我像下面这样写的时候 我可以得到这个输出。 输出 我认为test[0]=100->test[0]^1=101,但它不是。 你能解释一下有什么不同吗?

  • 我有一个问题,我的二进制搜索算法寻找2的平方根似乎是在一个无限循环中,并永远运行: 我不确定我的while循环是否存在问题。我认为这将是一个非常直接的二进制搜索算法,只需稍加修改即可适应平方根方面。 当运行我的代码时,我似乎无法让它产生任何输出。我不确定代码或编译器是否存在真正的问题,因为我认为我遵循的算法与过去非常接近。

  • 问题内容: 我是Java开发人员,我想知道如何在Java程序中使用Scala? 问题答案: 去阅读 Daniel Spiewak 关于Scala 的优秀博客系列。使用Scala,您可以保持: 您所有的Java库 在JVM上运行的所有优势(普遍性,管理工具,性能分析,垃圾回收等) 但是您可以编写Scala代码: 比Java更简洁明了(尤其是使用更多的 功能 样式,例如在collections库中)