最小生成树之Kruskal算法的python实现

所有生成树中,边总权和最小的生成树称为G的最小生成树(Minimum Spanning Tree, MST)。最小生成树的常用算法有Prim算法(适用于稠密图)、Kruskal算法(贪心思想,适用于稀疏图)。在实际应用中,许多问题的图论模型都是最小生成树,如通信网络建设、有线电缆铺设、加工设备分组等。

1. NetworkX

直接调NetworkX的API

  • 代码
import networkx as nx 
import numpy as np
import matplotlib.pyplot as plt

# 邻接矩阵,0表示不邻接
adj_arr = np.array([[0, 7, 0, 0, 0, 5],
                    [7, 0, 9, 0, 3, 0],
                    [0, 9, 0, 6, 0, 0],
                    [0, 0, 6, 0, 8, 10],
                    [0, 3, 0, 8, 0, 4],
                    [5, 0, 0, 10, 4, 0]])

# 由邻接矩阵创建NetworkX图
Graph = nx.from_numpy_array(adj_arr)

# 方式1: 采用kruskal算法求该图的最小生成树
min_span_tree = nx.minimum_spanning_tree(Graph, algorithm='kruskal')
# 方式2: 采用prim算法直接获取该图最小生成树的边
# data=False表示返回值不带权重
min_span_tree_edges = nx.minimum_spanning_edges(Graph, algorithm='prim', data=False)

# 绘图
plt.figure(figsize=(7, 5), dpi=100)
pos = nx.spring_layout(Graph)
nx.draw_networkx(Graph, pos)
node_labels = nx.get_node_attributes(Graph, 'node_name')
nx.draw_networkx_labels(Graph, pos, labels=node_labels)
edge_labels = nx.get_edge_attributes(Graph, 'weight')
nx.draw_networkx_edge_labels(Graph, pos, edge_labels=edge_labels)
plt.show()

# 打印结果
print('图的边及权重:\n', Graph.edges(data=True))
# 无向图,对结果无影响
print('最小生成树的边= ', sorted(min_span_tree.edges()))
print('最小生成树的边= ', sorted(min_span_tree_edges))
  • 结果
    请添加图片描述

2. Kruskal算法

Kruskal算法:闭圈法。开始选择一条最小权的边,以后迭代中,总从与已选边不构成圈的那些未选边中,选择一条权最小的。(每一步中,如果有两条或两条以上的边都是权最小的边,则从中任意选一条)

  • 代码
import networkx as nx 
import numpy as np
import matplotlib.pyplot as plt

# 邻接矩阵,0表示不邻接
M = 1000  # 排除自身,如果不连通,则用一个极大值替代
adj_arr = np.array([[0, 7, M, M, M, 5],
                    [7, 0, 9, M, 3, M],
                    [M, 9, 0, 6, M, M],
                    [M, M, 6, 0, 8, 10],
                    [M, 3, M, 8, 0, 4],
                    [5, M, M, 10, 4, 0]])

node_num = len(adj_arr)  # 节点的数量

edges_num = 0  # 边的数量
edges_list = []
for i in range(node_num):
    for j in range(i+1, node_num):
        if adj_arr[i,j] < M:
            edges_num += 1
            edges_list.append([i, j, adj_arr[i][j]])
edges_list.sort(key=lambda x: x[2])  # 按照权的大小排序
print(node_num, edges_num, edges_list)

group = [[i] for i in range(node_num)]
res = []
for edge in edges_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(tuple(edge[0:2]))
        group[m] = group[m] + group[n]
        group[n] = []
  
print('Kruskal=', sorted(res))
  • 结果请添加图片描述
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最小生成树(Minimum Spanning Tree,MST)是图论中的一个基本问题,用于在一个连通、带权的无向图中找到一个生成树,使得树的所有边的权重之和最小。Python中有多种实现最小生成树的算法,其中最常用的是普里姆算法(Prim's algorithm)和克鲁斯卡尔算法Kruskal's algorithm)。 普里姆算法是一种贪心算法,从一个起始点开始,逐步扩展生成树,每次选择与当前树连接的最小权重的边,并将新的节点加入树中,直到生成树包含了图中的所有节点。 克鲁斯卡尔算法是一种基于边的贪心算法,它按照边的权重从小到大的顺序逐步加入生成树中,但要确保边的加入不会形成环路,直到生成树包含了图中的所有节点。 在Python中,可以使用NetworkX工具包来求解最小生成树问题。通过调用NetworkX中的函数,可以得到最小生成树的图或者最小生成树的边。例如,`minimum_spanning_tree()`函数返回的是一个由最小生成树构成的图,可以通过`T.edges()`方法获取最小生成树的边;`minimum_spanning_edges()`函数返回的是最小生成树的构成边,可以通过将其转换为列表数据进行操作。 此外,还有一种特殊的最小生成树问题,称为度限制最小生成树(Degree Constrained Minimum Spanning Tree)。在这种问题中,给定一个连通图和节点的度约束,需要在满足节点度约束的前提下,找到权重最小的生成树。这种问题在实际应用中常用于控制节点故障对整个系统的影响。 总结起来,Python中可以使用普里姆算法和克鲁斯卡尔算法来解决最小生成树问题,并且可以通过NetworkX工具包来实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值