从堆中间删除节点

问题描述 投票:5回答:3

只要可以在恒定时间内找到堆中的元素,就可以在O(lg n)中完成从堆中间删除节点的操作。假设堆的节点包含id作为其字段。现在,如果提供id,我们如何在O(lg n)时间删除节点?

一种解决方案是,我们可以在每个节点中都有一个位置的地址,在该地址中我们可以维护堆中节点的索引。该数组将按节点ID排序。但是,这需要维护其他阵列。是否有其他好的方法可以实现相同的效果。

PS:在实现Djikstra的最短路径算法时遇到了这个问题。

algorithm data-structures heap dijkstra
3个回答
1
投票

索引(id,节点)可以在具有O(1)查找复杂度(平均)的哈希表中单独维护。这样,总体复杂度仍为O(log n)。


0
投票

每个数据结构在设计时都考虑了某些操作。来自维基百科有关堆操作的信息

通常使用堆执行的操作是:create-heap:创建一个空堆find-max或find-min:分别找到最大堆的最大项或最小堆的最小项delete-max或delete-min:分别删除最大堆或最小堆的根节点增加键或减少键:分别在最大或最小堆内更新密钥插入:向堆添加新密钥merge连接两个堆以形成一个有效的新堆,其中包含两个堆的所有元素。

这意味着,堆不是您要查找的操作的最佳数据结构。我建议您寻找更合适的数据结构(取决于您的要求)。


0
投票

我遇到了类似的问题,这是我想出的:

解决方案1:如果删除某个随机项目的调用将具有指向该项目的指针,则可以将各个数据项目存储在堆之外;使这些项的堆为pointers;并让每个项目都包含其当前的堆数组索引。

[示例:堆包含具有键[2 10 5 11 12 6]的项的指针。保持值为10的项目具有一个名为ArrayIndex = 1(从0开始计数)的字段。因此,如果我有一个指向项目10的指针并想删除它,则只需查看其ArrayIndex并将其用于堆中即可正常删除。 O(1)查找堆位置,然后通常O(log n)通过递归heapify将其删除。

解决方案2:如果只有要删除的项目的键字段,而不是其地址,请尝试此操作。切换到一棵红黑树,将有效负载数据放入实际的树节点中。对于插入和删除,这也是O(log n)。它还可以在O(log n)中找到具有给定键的项,这使得按键删除继续为log n。

在这些方法之间,解决方案1将需要每次交换都不断更新ArrayIndex字段的开销。它还导致一种奇怪的一次性数据结构,下一个代码维护者将需要研究和理解。我认为解决方案2的速度差不多,并且优点是它是一种易于理解的算法。

© www.soinside.com 2019 - 2024. All rights reserved.