【问题标题】:why are priority queues implemented as binary heap?为什么优先级队列实现为二进制堆?
【发布时间】:2023-04-03 04:45:02
【问题描述】:

为什么人们强调堆用于实现优先级队列,因为查看最大值/最小值的时间复杂度是 O(1) 。
通过使用指向最右边/最左边节点的指针,这也不能在 bst 上轻松实现。

【问题讨论】:

  • 您无法在 O(1) 时间内访问 BST 中最左边/最右边的节点。
  • @EJP 我想到了 c++ stl map 问这个......它实现了红黑树并有这个成员函数'end'它返回你在常量时间内的最大值......非常类似于我们如何访问链表的最后一个节点。
  • 获取迭代器是O(1)。迭代它不是。

标签: c++ heap binary-search-tree priority-queue


【解决方案1】:

鉴于您提出了基于 BST 的优先级队列,我将尝试向您解释为什么堆比 BST 更好。

堆是一棵完整的树;这是一棵完美平衡的树。它的高度是log_2(n+1)

如果这种方法是平衡的,那么 BST 方法是值得的。保持 BST 平衡的最著名技术是 AVL 树。这种树的高度界限为1.44 log_2(n+2) - 0.33

对于最低咨询,BST 的成本为 O(log(n)),而堆的成本为 O(1)。所以对于这个操作,堆显然更好。

对于插入和删除,成本是渐近等价的。但是 BST 往往更昂贵,因为它的高度往往高于完美平衡的树。此外,AVL 树比堆消耗更多的常数时间。在 AVL(以及其他平衡方法,红黑树、traps、splay 等)中,您执行轮换,而在堆中您执行交换,这比轮换便宜。

删除 BST 是一项复杂且成本高昂的操作,可能需要 O(log(n)) 轮换。使用堆是O(log(n)) swaps,它的召回比轮换便宜。

最终,在插入的情况下,您可以对堆执行O(log(n)) 交换,对 AVL 执行最多两次轮换。但是在插入 AVL 时,您需要执行不成功的搜索,而在堆中您可以在开始交换之前直接插入新密钥。我认为只有插入 BST 有时才能击败一堆。但是,请考虑到您很可能会使用优先队列进行协商和删除;所以,如果是这种情况,那么您肯定会恢复插入时可能失去的时间。

此外,如果您使用存储完整树级别遍历的数组,则堆比 BST 更容易实现。在这种情况下,您不需要指针

【讨论】:

    【解决方案2】:

    可以,但是将其作为堆更有效,并且可以说更简单,因为堆的顶部比树的最左边的元素更容易跟踪(堆的顶部只是第一个元素的基础序列)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-10
      • 1970-01-01
      • 2011-10-18
      • 2013-03-16
      • 1970-01-01
      • 2017-10-18
      • 2013-11-30
      • 1970-01-01
      相关资源
      最近更新 更多