版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/AivenZhong/article/details/84397752
prim算法和dijkstra算法基本思路一模一样,都是贪婪。都是从costs边数组里面找最短边,把这个最短边的结点加入t(已经确定好最短边的点)中。然后再遍历这个结点的邻边,更新costs。
但是prim和dijkstra的区别在哪里呢?
- dijkstra的costs,costs的每个值存的是开始点到该点的路径权值总和
- 而prim的costs,costs的每个值存的是该点到该点父结点的边权,只有一条边的权值,不像dijkstra那样把之前走过的路径加上。
- 最后生成的生成树也不一样,dijkstra生成的是单源最短路径生成树,就是一个点到其他点的路径树,一般应用于运输;prim生成的是总路径最短生成树,就是这种树既把所有点连在一起,而且该树的总权值最小,一般应用于建造铺设。
- 后面的更新costs的时候,判断条件不一样。dijkstra在结点里面找边的时候,边权值加上该结点小于之前的costs就更新;而prim找边的时候,直接用边权值和之前的costs比,小于就更新。
图:
python代码
# 最小生成树python实现
def prim(graph):
n = len(graph)
costs = [99999 for _ in range(n)] # 父结点到该结点的边权值
costs[0] = 0
parents = [-1 for _ in range(n)]
visited = [False for _ in range(n)]
t = []
while len(t) < n:
# 在costs找最短边,把该最短边的结点加入t,标记为已访问
minCost = 99999
minNode = None
for i in range(n):
if not visited[i] and costs[i] < minCost:
minCost = costs[i]
minNode = i
t.append(minNode)
visited[minNode] = True
# 遍历该结点的边,更新最短边
for edge in graph[minNode]:
if not visited[edge[0]] and edge[1] < costs[edge[0]]:
costs[edge[0]] = edge[1]
parents[edge[0]] = minNode
return costs, parents
data = [
[2, 0, 1],
[2, 1, 5],
[2, 3, 5],
[2, 4, 5],
[2, 5, 4],
[0, 1, 6],
[0, 3, 5],
[4, 1, 3],
[4, 5, 6],
[5, 3, 2],
]
# 构造邻接表
n = 6
graph = [[] for _ in range(n)]
for edge in data:
graph[edge[0]].append([edge[1], edge[2]])
graph[edge[1]].append([edge[0], edge[2]])
# 最小生成树MST
print('MST')
costs, parents = prim(graph)
print('costs:', costs)
print('parents', parents)
total = 0
for cost in costs:
total += cost
print('Total cost of MST:', total)
# 运行结果
# MST
# costs: [0, 5, 1, 2, 3, 4]
# parents [-1, 2, 0, 5, 1, 2]
# Total cost of MST: 15