【问题标题】:Tracking a node inside an heap跟踪堆内的节点
【发布时间】:2013-03-02 01:21:42
【问题描述】:

我有这个问题 - 我正在保留一个包含两个不同堆的数据结构,一个最小堆和一个最大堆,包含相同的数据。

我的目标是为任一堆中的每个节点位置保留某种记录,并使用堆操作对其进行更新。 底线 - 我试图弄清楚我怎样才能拥有一个在 lg(n) 复杂性中工作的 delete(p) 函数。 p 是一个指针数据对象,可以保存任何数据。

谢谢, 内德。

【问题讨论】:

    标签: algorithm data-structures heap


    【解决方案1】:

    如果您的堆被实现为一个项目数组(例如引用),那么您可以在 O(n) 时间内轻松地在堆中找到任意项目。一旦您知道该项目在堆中的位置,您就可以在 O(log n) 时间内将其删除。所以查找和删除是 O(n + log n)。

    如我在this answer 中所述,如果将堆与字典或哈希映射配对,则可以实现 O(log n) 删除。

    解释了在 O(log n) 时间内删除任意项目here

    字典方法的诀窍是字典包含一个键(项目键)和一个值,该值是节点在堆中的位置。每当您在堆中移动一个节点时,都会在字典中更新该值。在这种情况下,插入和删除会稍微慢一些,因为它们需要进行 log(n) 字典更新。但是这些更新是 O(1),所以它并不是非常昂贵。

    或者,如果您的堆实现为二叉树(带有指针,而不是数组中的隐式结构),那么您可以将指向节点的指针存储在字典中,而不必在插入时更新它或从堆中删除。

    话虽如此,在配对数据结构中添加和删除最小值(或删除最大堆的最大值)的实际性能将低于作为数组实现的标准堆,除非您进行大量任意删除。如果您只是偶尔删除一个任意项目,特别是如果您的堆相当小,那么 O(n) 删除性能可能会更好。实现起来更简单,当 n 较小时,O(n) 和 O(log n) 之间几乎没有真正的区别。

    【讨论】:

    • "... when n is small there's little real difference between O(n) and O(log n)" - 小心这样的陈述。人们可能不知道“小”是什么,甚至可能完全错过“当 n 很小时”。
    • 确实如此。良好的观察力。绝对不是我会对一群初级程序员说的话。 “小”绝对是一个主观的东西。对某些人来说,100 很小。对其他人来说,1,000 或 1,000,000。但是,“每隔一段时间”也是如此。如果有人错过了“当 n 很小时”……嘿,那是 他们的 问题!
    猜你喜欢
    • 2018-02-21
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    • 2021-09-01
    • 2016-10-06
    • 1970-01-01
    相关资源
    最近更新 更多