删除一些相关节点时,从优先级队列中弹出最高值

时间:2016-05-18 02:20:55

标签: algorithm graph stl graph-algorithm priority-queue

假设我们有一个图的n个节点的优先级队列。为每个节点分配一个密钥,并根据密钥值在优先级队列中对所有节点进行排序。

使用right implementation,从此队列中弹出头键(具有最高键值的节点)需要O(log(n))次。

但是如果还需要从优先级队列中删除头节点的所有扇出和扇区呢?显而易见的实现是搜索队列中的所有节点,如果它们处于扇形或扇形扇出,则将其删除。这将使POP的运行时间为O(nlog(n))

我们可以做得更好吗?有没有更好的数据结构可以提供更好的运行时间?

2 个答案:

答案 0 :(得分:0)

基本上,您需要的是具有额外删除操作的优先级队列。为了以有效的方式(即如果你想从队列中删除k个节点,它需要O(k * log n)),你需要一个节点上的句柄。

通常的做法是使用一个数组将顶点的id与优先级队列中的节点相关联。然后,删除算法取决于实现哪个优先级队列。

我不认为你在性能方面可以做得更好,因为维护排序数组的另一个解决方案更加昂贵(必须为每次修改维护数组)。

答案 1 :(得分:0)

在构建优先级队列时,构建一个哈希表,该表对于每个节点都具有其在用于承载优先级队列的阵列中的位置。现在,当您修改优先级队列时,通常通过交换数组中的两个元素来完成此操作。每次执行此操作时,都会更新哈希表中的值,以便它仍为每个节点保留优先级队列数组中的正确偏移量。这只是实现优先级队列的操作的恒定时间开销。

现在您需要做的是编写代码以获取任意节点,从哈希表中读取优先级队列中的偏移量,从优先级队列数组中删除该偏移量处的元素,然后删除该节点及其哈希表中的关联值。

唯一棘手的事情是从优先级队列数组中的任意位置删除一个元素(我将其作为堆)并恢复堆的不变量。每个元素最多只有一个父元素,最多两个子元素。假设最高优先级位于顶部,则每个元素必须不高于其父元素,并且至少与其子元素一样高。如果您现在将具有最大有效数组索引的元素与要移除其元素的元素交换,则可以增加或减少,因此您可以中断这两个不变量中的一个,但不能同时断开这两个不变量。

如果元素现在大于其父元素,则使用向堆顶部移动的标准堆不变修复方法。这只能增加它所替换的元素中的键,所以当它完成时,会恢复堆不变量。如果元素现在小于其中一个孩子(更有可能),则将其与这两个孩子中较大的一个交换,并照常进行。

在任何一种情况下,这相当于标准堆筛选或筛选(使用额外的簿记来保持哈希表最新)所以成本为O(log n))。

(或者,根本不要使用优先级队列,而是使用像Java TreeMap或TreeSet这样的数据结构,这是一个关联数组,其操作允许您检索具有最大(或最小)的数组中的元素)键在这种情况下你几乎没有实现,每个操作仍然是O(log n)。