基於矩陣實現的最小生成樹演算法
阿新 • • 發佈:2019-01-09
1.最小生成樹
在Wikipedia中最小生成樹(Minimum Spanning Tree)的定義如下:A minimum spanning tree is a spanning tree of a connected, undirected graph. It connects all the verticestogether with the minimal total weighting for its edges.但是,在本文中,我們主要介紹Prim演算法,Prim演算法同樣可以在Wikipedia中找到:
In computer science, Prim's algorithm is a greedy algorithm that finds a minimum spanning tree for a weighted undirected graph. This means it finds a subset of the edges that forms a tree that includes every vertex, where the total weight of all the edges in the tree is minimized. The algorithm operates by building this tree one vertex at a time, from an arbitrary starting vertex, at each step adding the cheapest possible connection from the tree to another vertex.
2.傳統演算法
2.1演算法描述
Prim的演算法思想很簡單:- 從圖中任選一個結點,放入最小生成樹集合中,
- 重複操作:找最小生成樹集合中所有結點的最近鄰接點,然後再放入到最小生成樹集合中,
- 當訪問完所有結點,即找到最小生成樹。
下面對演算法的圖例描述:
2.2演算法實現
Python實現如下:import numpy as np def prim(adjacencyMat, dimension, startVertex = 0): visited = np.zeros(dimension) distance = np.zeros(dimension) for i in range(dimension): distance[i] = np.inf tree = [] tree.append(startVertex) visited[startVertex] = 1 currentVertex = startVertex while not(len(tree) == dimension): for i in range(dimension): if not(adjacencyMat[currentVertex, i] == 0): if (visited[i] == 0) and (distance[i] > adjacencyMat[currentVertex, i]): distance[i] = adjacencyMat[currentVertex, i] # tree.append(i) minDist = np.inf for i in range(dimension): if(visited[i] == 0) and (distance[i] < minDist): minDist = distance[i] currentVertex = i tree.append(currentVertex) visited[currentVertex] = 1 print(tree) if __name__ == "__main__": adjacencyMat = np.array([[0,2,3,0,1], [0,0,0,0,7], [0,0,0,3,0], [0,0,0,0,0], [0,0,0,4,0]]) dimension = 5 prim(adjacencyMat, dimension)
3.基於矩陣的實現
3.1演算法描述
既然要採用矩陣的方式,那麼自然要用到鄰接矩陣,鄰接矩陣的定義如下:同時,我們用一個向量s表示訪問過的點集S,向量s定義:
另外,我們還需要一個向量d儲存向量s中每個點對應的距離值,向量d定義:
假設有一個圖,有5個點如:
那麼其鄰接矩陣是:
假設把點1作為起始點,那麼起始向量是:
演算法思想是,當向量s不全為無窮大(即結點沒有訪問完)時,重複以下三步:
- 計算argmin(s+d)。即取出s+d的最小值對應的點u的標記或索引。
- 把點u在向量s中對應位置的值改為無窮大。
- 計算表示點u到其他結點的距離,此時計算點u到點v的最小距離,如果點v在集合S中,那麼點u到點v的距離是0;如果點v不在集合S中,那麼求點u到點v的最小距離。如
3.2演算法實現
Python實現如下:from numpy.random import rand
import numpy as np
def init(dimension, startVertex = 0):
mat = rand(dimension, dimension)
mat[(rand(dimension) * dimension).astype(int), (rand(dimension) * dimension).astype(int)] = np.inf
vertexVec = np.zeros(dimension)
for i in range(dimension):
mat[i, i] = 0
vertexVec[startVertex] = np.inf
distanceVec = mat[0, :]
return mat, vertexVec, distanceVec
def minSpanningTree(adjacencyMat, vertexVec, distanceVec, startVertex, dimension):
treeVec = []
treeVec.append(startVertex)
distanceVec = list(distanceVec)
while(min(vertexVec) == 0):
vertexId = distanceVec.index(min(distanceVec + vertexVec))
vertexVec[vertexId] = np.inf
treeVec.append(vertexId)
for j in range(dimension):
if adjacencyMat[vertexId, :][j] < distanceVec[j]:
distanceVec[j] = adjacencyMat[vertexId, :][j]
print(treeVec)
if __name__ == "__main__":
dimension = 5
startVertex = 0
adjacencyMat, vertexVec, distanceVec = init(dimension, startVertex)
adjacencyMat1 = np.array([[0, 2, 3, np.inf, 1],
[np.inf, 0, np.inf, np.inf, 7],
[np.inf, np.inf, 0, 3, np.inf],
[np.inf, np.inf, np.inf, 0, np.inf],
[np.inf, np.inf, np.inf, 4, 0]])
distanceVec1 = adjacencyMat1[0, :]
treeVec = []
treeVec.append(startVertex)
minSpanningTree(adjacencyMat1, vertexVec, distanceVec1, startVertex, dimension)