在我看来,堆超过二叉树的唯一优势是在二进制树中以O(1)而不是O(log(2)n)的复杂度找到堆中的最小项。
实现优先级队列时,您需要从数据结构中删除每个最小的项目。从树中删除最小的项,并且两个堆都以O(log(2)n)的复杂度完成。 Althogh从树中删除项目可能更复杂。删除没有孩子的项目非常简单。
我的问题是为什么在实现优先级队列时使用堆而不是二叉树(在这种情况下更简单)?
答案 0 :(得分:11)
当二叉树收敛到数组时,二进制树情况下的最坏情况复杂度为O(n),而在堆中它仍为O(log(n))。你可以使用平衡的二进制树,如红黑或AVl,但随后它变得越来越复杂,需要更多的内存。
答案 1 :(得分:5)
堆通常更简单来实现,而不是正确平衡的二叉树。此外,它们需要更少的内存开销(元素可以直接存储在数组中,而不必分配树节点和指针以及所有内容),可能更快的性能(主要是由于使用单个连续数组的内存局部性)...为什么不会你使用它们吗?
答案 2 :(得分:5)
您的首选应取决于预期的访问模式,以及您可能存储的数据量:...
...但我建议您尽可能将选项保持为开放状态,这样您就可以至少对其中一个选项进行基准测试并切换到它,如果效果更好的话。
在过去的二十年里,我只参与了两个应用程序,其中堆是最好的选择(一次用于LRU,一次用于令人讨厌的操作 - 研究应用程序,恢复对随机扰动的k维超立方体的可加性,其中超立方体中的大多数细胞出现在k个不同的堆中,并且存储器是非常宝贵的)。然而,在这两种情况下,它们的表现远远超过其他选择:比平衡树或b树快几十倍。
对于我在上一段中提到的超立方体问题,我的团队负责人认为红黑树的表现比堆好,但基准测试显示红黑树的速度比较慢(我记得,它们是关于慢了二十倍),虽然b树明显更快,但是它们也很舒服地击败它们。
在我上面提到的两种情况下,堆的重要特征不是O(1)查找最小值,而是随机选择的元素的O(1)平均更新时间。
-James Barbetti(嗯,我以为我是。但验证码一直告诉我,我不是人类)
答案 3 :(得分:0)
首先,有不同的二叉树(其中一些很难,其中一些只提供平均O(log n)
),堆就是其中之一。
第二种:虽然大多数树上的操作都是O(log n)
,但它们更复杂,存在常数因素。
堆需要不断的额外内存,而树通常需要在每个节点中存储指针。
顺便说一下,堆很简单,只使用数组(我不确定如果它是用Java实现的,但我确实这么认为)
答案 4 :(得分:0)
如果您经常使用查找或搜索操作,则首选平衡二叉树。由于这个原因,线段交叉代码使用平衡树而不是堆。