prim演算法(最短生成樹) python實現
阿新 • • 發佈:2018-12-01
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