我正在研究Prim的算法。代码中有一个部分,切割的下一个顶点将到达属于MST
的顶点集。在这样做的同时,我们还必须“更新另一组中与离开顶点相邻的所有顶点”。这是来自CLRS
的快照:
有趣的部分在于行号。 11.但是由于我们在这里使用堆,我们只能访问最小元素,右(heap[0]
)?那么我们如何从堆中搜索和更新顶点,即使它们不是最小的顶点,因此除了线性搜索之外我们知道它们在哪里?
答案 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)