所以我正在遵循这个算法用于Prim的MST
输入:邻接列表形式的图G(V,E)
我班上给出的算法的时间复杂度分析如下:
O(V) => to build heap
O(VlogV) => V times EXTRACT_MIN operation
2E => traverse all edges in adjacency list
ElogV => E times DECREASE_KEY operation (Worst Case)
EXTRACT_MIN => O(logV)
DECREASE_KEY => O(logV)
Total Time Complexity = V + V*logV + 2E + E*log V
= O((V+E) logV)
我的问题是在执行decease键操作之前我不需要在min heap中找到相应的元素吗?并且搜索堆中的元素将花费O(V)时间。
对于上图,我会做这样的事情(使用数组实现最小堆)
A B C D E F
----------------------------------
chosen as min 0 INF INF INF INF INF ------> cost associated with vertices
------------------------------
A 7 2 6 INF INF
------------------------------
C 6 6 8 5
------------------------------
F 6 3 7
------------------------------
D 6 7
------------------------------
B 4
------------------------------
E
我的数组(最小堆)最初看起来像这样: 每个元素由两部分组成:顶点名称和成本。 最小堆基于成本。
A,0 | B,INF | C,INF | D,INF | E,INF | F,INF
现在在获得第一个最小元素(A)后,我在邻接列表中查找其相邻顶点 找到B,C和D.现在我需要对最小堆中的这些顶点执行减少键操作。
只有当我知道要执行减少键操作的顶点索引时,DECREASE_KEY操作才有效。 要获得索引,我不需要首先在数组中搜索它需要额外的O(V)吗?
答案 0 :(得分:1)
好吧,你可以以你想要的方式解决这个问题。它需要将指针从每个顶点保持回到堆中的索引。每当交换堆中的元素时,都会调整两个相关顶点上的指针。然后,当您需要调整顶点的键时,您可以将指针移回堆中的索引。
但是,我通常不这样做......
我通常将(成本,顶点)记录放在堆中,每当顶点的成本下降时,我就会添加一个新的记录。当我从堆中弹出一个顶点时,如果它已经完成,我就忽略它。你必须跟踪最终完成的顶点,这很容易。
这需要O(| E |)空格而不是O(| V |),但这通常不是什么大问题,时间复杂度保持不变。