堆(综述)

                     

贡献者: 待更新

   (本文根据 CC-BY-SA 协议转载自原搜狗科学百科对英文维基百科的翻译)

图
图 1:二叉堆的示例,其中节点为 1 到 100 之间的整数。

   在计算机科学中,堆是一种特殊的基于树的数据结构,本质上是一棵几乎完全的[1]树,它满足堆属性:在最大堆中,对于任意给定的节点 C,如果 P 是 C 的父节点,那么 P 的键(值)大于或等于 C 的键。在最小堆中,P 的键小于或等于 C 的键。堆 “顶部” 的节点(没有父节点)称为根节点。

   堆是称为优先队列的抽象数据类型的最有效实现,事实上优先队列通常被称为 “堆”,不管它们是如何实现的。在堆中,最高(或最低)优先级的元素总是存储在根节点。然而,堆不是排序结构,它可以被认为是部分有序的。当需要重复移除优先级最高(或最低)的对象时,堆是一种有用的数据结构。

   堆的一个常见实现是二叉堆,其中树是二叉树(见图)。堆数据结构,特别是二叉堆,是由 J. W. J. Williams 在 1964 年引入的,作为堆排序算法的数据结构。[2] 堆在一些高效的图算法中也很重要,比如 Dijkstra 算法。当堆是一棵完全二叉树时,它有一个最小的可能高度——一个有 N 个节点的堆,对于每个节点,一个分支总是有 loga N 的高度。

   注意,如图所示,兄弟和堂兄弟之间没有隐含的排序,也没有有序遍历的隐含序列(例如,在二叉搜索树中)。上面提到的堆关系仅适用于节点和它们的父亲、祖父等之间。每个节点可以拥有的最大子节点数取决于堆的类型。

1. 操作

   涉及堆的常见操作有:

   基础

   创建

   检查

   内部的

2. 实现

图
图 2:一个完全二叉最大堆的例子,节点是从 1 到 100 之间的整数。图示了它将如何存储在数组中。

   堆通常在数组(固定大小或动态数组)中实现,并且不需要元素之间的指针。元素插入堆或从堆中删除后,可能会违反堆性质,必须通过内部操作来平衡堆。

   二叉堆可以用单独使用数组的非常节省空间的方式来表示。第一个(或最后一个)元素将包含根元素。数组接下来两个元素包含根元素的孩子。接下来的四个包含两个子节点的四个子节点,等等。因此,在位置 n 的节点的子节点将在以 1 为起点编号数组的 2n 和 2n+1 位置,或者 “以 0 为起点编号数组的 2n+1 和 2n+2 位置。这允许通过简单的索引计算来向上或向下移动树。允许通过向上筛选或向下筛选操作(交换无序元素)来完成平衡堆。因为我们可以从一个数组构建一个堆,而不需要额外的内存(例如,对于节点),所以 heapsort 可以用来就地排序一个数组。

   不同类型的堆以不同的方式实现操作,但值得注意的是,插入通常是通过在堆的末尾第一个可用空间中添加新元素来完成的。这通常会违反堆性质,因此元素会被向上筛选,直到堆性质被重新建立。类似地,删除根元素是通过移动根元素,然后将最后一个元素放入根并向下筛选以重新平衡。因此,替换是通过删除根并将新元素放入根并向下筛选来完成的,和先 pop(向下筛选最后一个元素),再 push(向上筛选新元素)后相比,避免了向上筛选步骤。

   从给定的元素数组中构造二叉(或 d 叉)堆可以使用经典弗洛伊德算法在线性时间内执行,最差情况下的比较次数等于 2N − 2s2(N) − e2(N) (对于二叉堆),其中 s2(N)是 N 的二进制表示的所有数字的总和,e2(N)是 N 的素数因子分解中的 2 的指数,[6] 这比连续插入原始空堆的序列更快,该操作是对数线性的。

3. 变体

4. 变体理论界限的比较

   以下是各种堆数据结构的时间复杂度。函数名假设一个最小堆。

   In the following time complexities[7] O(f) is an asymptotic upper bound and Θ(f) is an asymptotically tight bound (see Big O notation). Function names assume a min-heap.

图
图 3
  1. Each insertion takes $O( \log\left(k\right) )$ in the existing size of the heap, thus $$\sum_{k=1}^N O(\log k).~$$ Since $$\log \frac{n}{2} = (\log n) - 1,~$$ a constant factor (half) of these insertions are within a constant factor of the maximum, so asymptotically we can assume $k = n$; formally the time is $$ n O(\log n) - O(n) = O(n \log n).~$$ This can also be readily seen from Stirling's approximation.
  2. Brodal and Okasaki later describe a persistent variant with the same bounds except for decrease-key, which is not supported. Heaps with $n$ elements can be constructed bottom-up in $O(n)$.
  3. Amortized time.
  4. Lower bound of $\Omega(\log \log n)$, upper bound of $O(2^{2\sqrt{\log \log n}})$.
  5. $n$ is the size of the larger heap.
  1. 在堆的现有大小中,每次插入的时间复杂度为 $O(\ \log\left(k\right) )$,因此由于这些插入的常数薪资(一半)在最大常数因子内,因此我们可以渐进地假设;形式上的时间是。这也可以从弗斯特林公式中很容易看出。
  2. 跳到:$a b c d e f g h i$ 摆平时间
  3. $n$ 是较大堆的大小。
  4. 下界 上界
  5. Brodal 和 Okasaki 后来描述了一个具有相同边界的持久变体,除了 reduce-key,这是不受支持的。具有 $n$ 个元素的堆可以在 $O(n)$ 中自下而上地构建。

5. 应用

   堆数据结构有许多应用。

6. 实现_F

7. 参考文献

   [1] ^CORMEN, THOMAS H. (2009). INTRODUCTION TO ALGORITHMS. United States of America: The MIT Press Cambridge, Massachusetts London, England. pp. 151–152. ISBN 978-0-262-03384-8..

   [2] ^Williams, J. W. J. (1964), "Algorithm 232 - Heapsort", Communications of the ACM, 7 (6): 347–348, doi:10.1145/512274.512284.

   [3] ^The Python Standard Library, 8.4. heapq — Heap queue algorithm, heapq.heappush.

   [4] ^The Python Standard Library, 8.4. heapq — Heap queue algorithm, heapq.heappop.

   [5] ^The Python Standard Library, 8.4. heapq — Heap queue algorithm, heapq.heapreplace.

   [6] ^Suchenek, Marek A. (2012), "Elementary Yet Precise Worst-Case Analysis of Floyd's Heap-Construction Program", Fundamenta Informaticae, IOS Press, 120 (1): 75–92, doi:10.3233/FI-2012-751..

   [7] ^Cormen, Thomas H.(英语:Thomas H. Cormen); Leiserson, Charles E. ; Rivest, Ronald L. (1990). Introduction to Algorithms (1st ed.). MIT Press and McGraw-Hill. ISBN 0-262-03141-8.CS1 maint: Multiple names: authors list (link).

   [8] ^Fredman, Michael Lawrence; Tarjan, Robert E. (July 1987). "Fibonacci heaps and their uses in improved network optimization algorithms" (PDF). Journal of the Association for Computing Machinery. 34 (3): 596–615. doi:10.1145/28869.28874..

   [9] ^Iacono, John (2000), "Improved upper bounds for pairing heaps", Proc. 7th Scandinavian Workshop on Algorithm Theory (PDF), Lecture Notes in Computer Science, 1851, Springer-Verlag, pp. 63–77, arXiv:1110.4428, doi:10.1007/3-540-44985-X_5, ISBN 3-540-67690-2.

   [10] ^Brodal, Gerth S. (1996), "Worst-Case Efficient Priority Queues" (PDF), Proc. 7th Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 52–58.

   [11] ^Haeupler, Bernhard; Sen, Siddhartha; Tarjan, Robert E. (November 2011). "Rank-pairing heaps" (PDF). SIAM J. Computing: 1463–1485. doi:10.1137/100785351..

   [12] ^Brodal, G. S. L.; Lagogiannis, G.; Tarjan, R. E. (2012). Strict Fibonacci heaps (PDF). Proceedings of the 44th symposium on Theory of Computing - STOC '12. p. 1177. doi:10.1145/2213977.2214082. ISBN 9781450312455..

   [13] ^Goodrich, Michael T.; Tamassia, Roberto (2004). "7.3.6. Bottom-Up Heap Construction". Data Structures and Algorithms in Java (3rd ed.). pp. 338–341. ISBN 0-471-46983-1..

   [14] ^Fredman, Michael Lawrence (July 1999). "On the Efficiency of Pairing Heaps and Related Data Structures" (PDF). Journal of the Association for Computing Machinery. 46 (4): 473–501. doi:10.1145/320211.320214..

   [15] ^Pettie, Seth (2005). Towards a Final Analysis of Pairing Heaps (PDF). FOCS '05 Proceedings of the 46th Annual IEEE Symposium on Foundations of Computer Science. pp. 174–183. CiteSeerX 10.1.1.549.471. doi:10.1109/SFCS.2005.75. ISBN 0-7695-2468-0..

   [16] ^Frederickson, Greg N. (1993), "An Optimal Algorithm for Selection in a Min-Heap", Information and Computation (PDF), 104 (2), Academic Press, pp. 197–214, doi:10.1006/inco.1993.1030.


致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择大量广告以及内容付费等。 因此,我们请求广大读者热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 20 元,我们一周就能脱离亏损, 并在接下来的一年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。

                     

友情链接: 超理论坛 | ©小时科技 保留一切权利