这里简单讲解一下普利姆算法的实现

伪码如下:

 1 color[n]    color[v]用于记录v的访问状态WHITE(未访问顶点),GRAY(队列中的顶点),BLACK(访问结束的顶点)
 2 M[n][n]     邻接矩阵,M[u][v]记录u到v的边的权值
 3 d[n]        d[v]用于记录连接T内顶点与V-T内顶点的边中,权值最小的边的权值
 4 p[n]        p[v]用于记录MST中顶点v的父节点
 5 
 6 prim()
 7     将所有顶点u的color[u]设置为WHITE,d[u]初始化为INFTY
 8     d[0] = 0
 9     p[0] = -1
10 
11     while(true)
12         mincost = INFTY
13         // 扫描点集合,选出一个距离当前MST最近的点
14         for i 从 0 至 n-1
15             if color[i] != BLACK && d[i] < mincost
16                 mincost = d[i]
17                 u = i;
18         
19         if mincost == INFTY
20             break
21 
22         color[u] = BLACK
23 
24         // 选出点后,扩展MST,并更新其他点到MST的距离
25         for v 从 0 至 n-1
26             if color[v] != BLACK且u和v之间存在边
27                 if M[u][v] < d[v]
28                     d[v] = M[u][v]
29                     p[v] = u
30                     color[v] = GRAY
31                     

实现过程简述:

 

 初始时刻,MST为空集

设置0节点到MST的距离为0

则第一次选离MST最近的节点一定是0节点

选中0节点之后,MST得到扩展,此时用0节点更新其他节点到MST的距离

这个意思就是说,每次选中一个节点过后,MST扩充了这个新节点,其他节点到MST的距离要更新,而这里所谓的其他节点,其实就是新节点的近邻

因为其他和新节点无关的节点,到MST的距离已经在之前就更新过了,所以这里只需要更新新节点的近邻就行

然后循环,在更新距离过后的新距离向量里选取最近节点,直到所有节点选完,跳出循环

这里p数组,用来记录MST中父节点信息,在计算MST最小权值是没用的,但是在生成MST和相关的信息查询时会起到很大作用

上述算法实现的时间复杂度是O(V²)

 

优化:

用二叉堆/优先队列来选择边,可以提高算法时间效率

每次选择新边不用再扫一遍所有点集合了,直接从二叉堆里取最小边即可,用最小堆优化的时间复杂度是O(VlogV + ElogV),使用斐波那契堆优化O(E + VlogV)。

这里使用邻接表的效率比邻接矩阵高,因为在新节点加入MST后,要扫新节点的邻近节点,邻接表就可以直接拿到,邻接矩阵得扫所有节点

posted on 2020-09-20 11:40  高数考了59  阅读(191)  评论(0)    收藏  举报