c++ - 维护堆属性

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

  • 简要背景:我正在研究插入发生时维护堆属性的步骤。这是一个有趣的问题:

  • 问题:有两种通用策略可用于维护堆属性:

    1. 确保树是完整的,然后修复排序或
    2. 首先确保顺序正确,然后检查完​​整性。

哪个更好(1 或 2)?

引用:http://www.cs.sfu.ca/CourseCentral/225/johnwill/cmpt225_09heaps.pdf (堆插入 - 幻灯片 16)由 John Edgar 博士撰写。

如果你们能阐明为什么上述方法之一更好,那就太好了?

最佳答案

将二叉堆实现为数组,通常有两种实现插入的方法:自上而下或自下而上。链接 PDF 的幻灯片 17 描述了自下而上的做事方式。它将新项目添加到堆的末尾(最底部、最左侧的位置),并将其向上冒泡。这是幻灯片 16 中显示的策略 1 的实现。

从性能的角度来看,这是更好的方法,因为平均,它需要更少的迭代来修复排序。参见 Argument for O(1) average-case complexity of heap insertion详细解释为什么会这样。

自上而下的方法,对应于幻灯片 16 上的策略 2,要求每次插入都进行 O(log n) 比较。该策略从根开始,通过堆向下筛选项目。如果新项小于(在最小堆中)与它进行比较的节点,它会替换该节点上的项,并且必须下推刚刚替换的项。这一直持续到您到达堆的底部。不存在“提前退出”的可能,因为您最终必须在叶级将新项目放入堆中。

我从来没有真正认为它是先确保顺序,然后再确保完整性,但这基本上就是自上而下方法所做的事情。

第二种策略每次插入需要更多的迭代,并且在每次迭代期间也做更多的工作来维持顺序。

关于c++ - 维护堆属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47666318/

相关文章:

c - 最长路径: Recursive Backtracking with Constraints in C

java - 排序父子关系

algorithm - 从 Just Inorder Traversal 中查找预序?

c++ - 关于C++中的make_heap算法

java - 为什么不使用堆数组的元素零?

c++ - SDL Destructor 过早调用

c++ - 使用 C++ 提供静态文件

c++ - 在 Qt 中的对象之间发送自定义事件而不关联它们

android - OpenCV 未定义对 cv::SURF::SURF() eclipse 的引用

java - 我的就地堆排序代码有什么问题