prim算法(最短生成树) python实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/AivenZhong/article/details/84397752

prim算法和dijkstra算法基本思路一模一样,都是贪婪。都是从costs边数组里面找最短边,把这个最短边的结点加入t(已经确定好最短边的点)中。然后再遍历这个结点的邻边,更新costs。

但是prim和dijkstra的区别在哪里呢?

  1. dijkstra的costs,costs的每个值存的是开始点到该点的路径权值总和
  2. 而prim的costs,costs的每个值存的是该点到该点父结点的边权,只有一条边的权值,不像dijkstra那样把之前走过的路径加上。
  3. 最后生成的生成树也不一样,dijkstra生成的是单源最短路径生成树,就是一个点到其他点的路径树,一般应用于运输;prim生成的是总路径最短生成树,就是这种树既把所有点连在一起,而且该树的总权值最小,一般应用于建造铺设。
  4. 后面的更新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

猜你喜欢

转载自blog.csdn.net/AivenZhong/article/details/84397752