# 最小生成树之Prim算法和Kruskal算法

## Prim算法

1. 输入：一个加权连通图，其中顶点集合为V，边集合为E；

2. 初始化：Vn = {x}，其中x为集合V中的任一节点（起始点），Enew = {}；

3. 重复下列操作，直到Vn = V：（在集合E中选取权值最小的边（u, v），其中u为集合Vn中的元素，而v则是V中没有加入Vn的顶点（如果存在有多条满足前述条件即具有相同权值的边，则可任意选取其中之一）；
将v加入集合Vn中，将（u, v）加入集合En中；）

4. 输出：使用集合Vn和En来描述所得到的最小生成树。

## Prim算法实现

class MST(object):
def __init__(self, graph):
self.graph = graph
self.N = len(self.graph)
pass
def prim(self, start):
index = start
cost, path = [0] * self.N, [0] * self.N
# 初始化起点
known = [x for x in map(lambda x: True if x == start else False, [x for x in range(self.N)])]
path[start] = -1
for i in range(self.N):
cost[i] = self.graph[start][i]
# 遍历其余各个结点
for i in range(1, self.N):
mi = 1e9
# 找出相对最小权重的结点
for j in range(self.N):
if not known[j] and mi > cost[j]:
mi, index = cost[j], j
# 计算路径值
for j in range(self.N):
if self.graph[j][index] == mi:
path[index] = j
known[index] = True
# 更新index连通其它结点的权重
for j in range(self.N):
if not known[j] and cost[j] > self.graph[index][j]:
cost[j] = self.graph[index][j]
print(path)
# 图用临接矩阵表示
MST([
[1e9, 6, 8, 1e9, 7, 1e9, 1e9, 1e9],
[6, 1e9, 7, 1e9, 1e9, 3, 4, 1e9],
[8, 7, 1e9, 1e9, 1e9, 1e9, 6, 1e9],
[1e9, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9, 2],
[7, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9, 1e9],
[1e9, 3, 1e9, 1e9, 1e9, 1e9, 1e9, 9],
[1e9, 4, 6, 1e9, 1e9, 1e9, 1e9, 7],
[1e9, 1e9, 1e9, 2, 1e9, 9, 7, 1e9],
]).prim(0)
path结果为：[-1, 0, 6, 7, 0, 1, 1, 6]

## Kruskal算法实现

class Edge(object):
def __init__(self, start, end, weight):
self.start = start
self.end = end
self.weight = weight
def getEdges(self):
edges = []
for i in range(self.vertex):
for j in range(i+1, self.vertex):
if self.graph[i][j] != 1e9:
edge = Edge(i, j, self.graph[i][j])
edges.append(edge)
return edges

def kruskal(self):
union = dict.fromkeys([i for i in range(self.vertex)], -1)  # 辅助数组，判断两个结点是否连通
self.edges = self.getEdges()
self.edges.sort(key=lambda x: x.weight)
res = []
def getend(start):
while union[start] >= 0:
start = union[start]
return start
for edge in self.edges:
# 找到连通线路的最后一个结点
n1 = getend(edge.start)
n2 = getend(edge.end)
# 如果为共同的终点则不处理
if n1 != n2:
print('{}----->{}'.format(n1, n2))
(n1, n2) = (n2, n1) if union[n1] < union[n2] else (n1, n2)
union[n2] += union[n1]
union[n1] = n2
res.append(edge)
print(union.values())

• 本文已收录于以下专栏：

## 最小生成树（Prim算法和Kruskal算法）—理解与论证

• MathThinker
• 2015年08月23日 17:16
• 1992

## 最小生成树Prim与Kruskal算法的比较

• Mollnn
• 2016年09月19日 21:48
• 3758

## 【最小生成树】Prim算法和Kruskal算法的区别对比

Prim算法和Kruskal算法都是从连通图中找出最小生成树的经典算法。从策略上来说，Prim算法是直接查找，多次寻找邻边的权重最小值，而Kruskal是需要先对权重排序后查找的。 所以说，Kr...
• liuchuo
• 2016年12月21日 21:59
• 1667

## Prim算法和Kruskal算法的基本思想和实现

• SCaryon
• 2017年06月28日 22:14
• 924

## 数学建模（14）——MATLAB实现最小生成树（Prim与Kruskal算法）

Prim算法 连通赋权图如上 邻接矩阵如下 0 50 60 0 0 0 0 0 0 0 65 40 ...
• longxinghaofeng
• 2017年09月06日 21:14
• 920

## 最小生成树的两种算法：Prim和Kruskal算法

• I_am_a_winer
• 2015年04月25日 22:42
• 1529

## Prim算法 Kruskal算法 简述

Prim算法和Kruskal算法，都是用来找出图中最小生成树的算法，两个算法有些小差别。 Prim算法 又称普里姆算法，以图上的顶点为出发点，逐次选择到最小生成树顶点集距离最短的顶点为最小生成...
• jerry81333
• 2017年01月25日 06:28
• 742

## 图 之 MST（最小生成树 — kruskal算法 ）并查集实现

#并查集的优化： （1）       Find_Set(x)时，路径压缩寻找祖先时，我们一般采用递归查找，但是当元素很多亦或是整棵树变为一条链时，每次Find_Set(x)都是O(n)的复杂度。为...
• PeersLee
• 2015年12月26日 17:41
• 1778

## [C++]最小生成树--Prim算法&Kruskal算法

• stary_yan
• 2016年05月16日 20:24
• 8021

## 图论中最小生成树构造算法之Prim算法和Kruskal算法

• yanerhao
• 2015年06月25日 16:24
• 2542

举报原因： 您举报文章：最小生成树之Prim算法和Kruskal算法 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)