Python实现最小生成树:Kruskal与Prim算法详解
本文详细解析Python中Kruskal与Prim两种最小生成树算法的实现逻辑。Kruskal通过边权重排序及并查集思想构建,Prim则基于节点分组与贪心策略扩展。文章提供完整的Graph类代码示例及运行结果,帮助开发者理解算法核心差异与适用场景。
Kruskal算法的核心逻辑在于边的处理:首先将所有边按照权重值从小到大进行排序,随后依次遍历排序后的边。在选取过程中,若当前边的两个端点属于不同的连通分量,则将该边加入最小生成树;若两端点已在同一分量中,则跳过该边。此过程持续进行,直至遍历完所有边或生成树构建完成。
Prim算法则侧重于节点的扩展:将所有节点划分为已选集合(selected_node,列表类型)和未选集合(candidate_node)。算法首先任意选取一个节点加入已选集合,随后遍历所有连接已选节点与未选节点的边,从中选取权重最小的一条边加入生成树,并将该边的尾节点从候选集合移至已选集合。循环直至候选集合为空。需注意,该算法要求图是连通的(边数至少为节点数减1),否则可能导致部分节点无法被访问从而引发死循环,因此在执行前需进行连通性校验。
#coding=utf-8
class Graph(object):
def __init__(self, maps):
self.maps = maps
self.nodenum = self.get_nodenum()
self.edgenum = self.get_edgenum()
def get_nodenum(self):
return len(self.maps)
def get_edgenum(self):
count = 0
for i in range(self.nodenum):
for j in range(i):
if self.maps[i][j] > 0 and self.maps[i][j] < 9999:
count += 1
return count
def kruskal(self):
res = []
if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
return res
edge_list = []
for i in range(self.nodenum):
for j in range(i,self.nodenum):
if self.maps[i][j] < 9999:
edge_list.append([i, j, self.maps[i][j]])#按[begin, end, weight]形式加入
edge_list.sort(key=lambda a:a[2])#已经排好序的边集合
group = [[i] for i in range(self.nodenum)]
for edge in edge_list:
for i in range(len(group)):
if edge[0] in group[i]:
m = i
if edge[1] in group[i]:
n = i
if m != n:
res.append(edge)
group[m] = group[m] + group[n]
group[n] = []
return res
def prim(self):
res = []
if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
return res
res = []
seleted_node = [0]
candidate_node = [i for i in range(1, self.nodenum)]
while len(candidate_node) > 0:
begin, end, minweight = 0, 0, 9999
for i in seleted_node:
for j in candidate_node:
if self.maps[i][j] < minweight:
minweight = self.maps[i][j]
begin = i
end = j
res.append([begin, end, minweight])
seleted_node.append(end)
candidate_node.remove(end)
return res
max_value = 9999
row0 = [0,7,max_value,max_value,max_value,5]
row1 = [7,0,9,max_value,3,max_value]
row2 = [max_value,9,0,6,max_value,max_value]
row3 = [max_value,max_value,6,0,8,10]
row4 = [max_value,3,max_value,8,0,4]
row5 = [5,max_value,max_value,10,4,0]
maps = [row0, row1, row2,row3, row4, row5]
graph = Graph(maps)
print('邻接矩阵为\n%s'%graph.maps)
print('节点数据为%d,边数为%d\n'%(graph.nodenum, graph.edgenum))
print('------最小生成树kruskal算法------')
print(graph.kruskal())
print('------最小生成树prim算法')
print(graph.prim())
初始图的拓扑结构如下所示。

算法执行后的输出结果如下。

本文内容到此结束,希望上述解析能对您的学习有所帮助,欢迎继续支持本站获取更多技术资源。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









