如何为Prim的算法更新堆中的元素优先级?

时间:2013-06-12 21:15:12

标签: algorithm data-structures heap minimum-spanning-tree prims-algorithm

我正在研究Prim的算法。代码中有一个部分,切割的下一个顶点将到达属于MST的顶点集。在这样做的同时,我们还必须“更新另一组中与离开顶点相邻的所有顶点”。这是来自CLRS的快照:

enter image description here

有趣的部分在于行号。 11.但是由于我们在这里使用堆,我们只能访问最小元素,右(heap[0])?那么我们如何从堆中搜索和更新顶点,即使它们不是最小的顶点,因此除了线性搜索之外我们知道它们在哪里?

2 个答案:

答案 0 :(得分:9)

可以构建支持名为 reduce-key 的操作的优先级队列,该操作将现有对象的优先级置于优先级队列中并降低它。现有库附带的大多数优先级队列版本都不支持此操作,但可以通过多种方式构建它。

例如,给定二进制堆,您可以维护一个辅助数据结构,该结构从元素映射到二进制堆中的位置。然后,您将更新二进制堆实现,以便每次执行交换时,都会更新此辅助数据结构。然后,要实现reduce-key,您可以访问该表,在二进制堆中找到该节点的位置,然后继续冒泡步骤。

其他基于指针的堆如二项式堆或Fibonacci堆显式支持此操作(Fibonacci堆是专门为它设计的)。您通常有一个从对象到它们在堆中占用的节点的辅助映射,然后可以重新连接指针以在堆中移动节点。

希望这有帮助!

答案 1 :(得分:2)

指针启用高效的复合数据结构

你有这样的东西(使用伪代码C ++):

class Node
    bool visited
    double key
    Node* pi
    vector<pair<Node*, double>> adjacent //adjacent nodes and edge weights
    //and extra fields needed for PriorityQueue data structure
    // - a clean way to do this is to use CRTP for defining the base
    //   PriorityQueue node class, then inherit your graph node from that

class Graph
    vector<Node*> vertices

CRTP:http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

算法中的优先级队列Q包含Node* 类型的项目,其中ExtractMin为您提供最少{{1}的Node* }}

您不必进行任何线性搜索的原因是,当您获得key时,您拥有u = ExtractMin(Q)。因此,Node*可以获得u->adjacent中的v和每个相邻节点的 const时间中的G.Adj[u] 。由于您有一个指针w(u,v)到优先级队列节点( v),您可以在每个相邻节点的对数时间更新它在优先级队列中的位置(大多数优先级队列的实现)。

为了命名一些特定的数据结构,下面使用的v函数具有Fibonnaci堆和配对堆(摊销)的对数复杂度。

算法的更具体的伪代码

DecreaseKey(Q, v)