我正在尝试用C ++实现Prim的MST算法。我有一个设计问题
我实现了一个带有整数的min-heap,我们可以提取-min,减少key和insert-key。
现在正如我在Prim中所理解的那样,我需要保持每个顶点的权重,邻居信息。我的一些想法是:
1]定义结构
struct node {
int vertex;
int weight;
int neighbor;
};
使用min heap返回权重最小的节点。但问题是减少键,因为对于减少键,调用者需要传递他想要减少键的顶点。由于堆经常交换元素,我必须遍历整个列表以找到顶点,然后减少其键。这是O(n),我认为如果我这样做,Prim会变得更糟。
2]另一种方法是维护另一个数组,该数组跟踪最小堆队列中顶点的位置。但是在最小堆操作期间跟踪位置会很麻烦。
基本上,如果我必须执行减少键(v),如何在基于权重的最小堆队列中找到v。有没有优雅的方法来做到这一点?哪个仍然可以保持复杂性?
答案 0 :(得分:1)
您基本上确实需要在数据结构之间进行一些交叉引用。但是,你写了
但是在最小堆操作期间跟踪位置会很麻烦
这不是正确的。使用以下内容,您可以重用或编写不需要此功能的可重用数据结构。
首先,您的优先级队列需要公开某种iterator,这允许 O(1)访问。为此,您可以直接使用boost.Heap
(请参阅下面的注释),或者从那里了解界面的外观。
现在您使用另一个数据结构(在 O(1)中)将节点标签映射到队列的迭代器。例如,如果节点标签是(连续的)整数,则可以使用vector
个迭代器;如果他们基本上是其他任何东西,你应该使用unordered_map
。
每个节点结构还需要包含2中数据结构使用的标签。
第3项意味着您需要在上面的代码中添加以下内容。
struct node {
...
// Identifies
Label label;
};
请注意,这允许您将优先级队列与其他数据结构分离。当您执行decrease_key
并且node
在优先级队列中移动时,您无需担心任何事情,因为每个节点都包含label
成员。
说完所有这些之后,你还应该考虑使用已经有Prim算法的Boost Graph Library。