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

简介: 一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决。Prim算法输入:一个加权连通图,其中顶点集合为V,边集合为E;初始化:Vn = {x},其中x为集合V中的任一节点(起始点),Enew = {};重复下列操作,直到Vn = V:(在集合E中选取权值最小的边(u

一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据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来描述所得到的最小生成树。
以下面这张图作为例子,表格中的Vertex、Kown、Cost、Path分别表示顶点信息、是否访问过,权值,到达路径;
Prim算法
我们随机的选择顶点0作为起点,其执行步骤为:
步骤 选中结点
顶点0作为起始点 0
根据(6, 7, 8)的方案选中6 1
根据顶点1能够到达的权值(7, 4, 3)和顶点0能够到达的权值(7, 8)中选择3 5
根据顶点5能够到达的权值(8)和根据顶点1能够到达的权值(7, 4)和顶点0能够到达的权值(7, 8)中选择4 6
根据顶点6能够到达的权值(6, 7)和顶点0能够到达的权值(7)中选择6 2
根据顶点0能够到达的权值(7)和顶点6能够到达的权值(7)中选择7 4
根据顶点6能够到达的权值(7)选择7 7
根据顶点7能够到达的权值(2)选择2 3
全部结点都访问过,退出  

最终得到下面的结果,其中Path中的-1表示其作为起始点;Prim算法

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算法

构造一个只含n个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树的根节点,则它是一个含有n棵树的森林 。之后,从图的边集中选取一条权值最小的边,若该边的两个顶点分属不同的树 ,则将其加入子图,也就是这两个顶点分别所在的 两棵树合成一棵树;反之,若该边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林只有一棵树。kruskal算法能够在并查集的基础很快的实现。

以下面这张图作为例子,其中左边的表格是一个并查集,表示可以连通的结点。我们首先要根据权值对每条边进行排序,接着开始处理每一条边的情况。

最终得到下面的结果图:

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
接下来就是kruskal函数:
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())
其中union打印出来的结果和图中是一致的,为[3, 3, 5, 6, 6, 6, -8, 3]。

目录
相关文章
|
3月前
|
算法 决策智能
基于prim算法求出网络最小生成树实现网络社团划分和规划
该程序使用MATLAB 2022a版实现路线规划,通过排序节点权值并运用Prim算法生成最小生成树完成网络规划。程序基于TSP问题,采用遗传算法与粒子群优化算法进行路径优化。遗传算法通过编码、选择、交叉及变异操作迭代寻优;粒子群优化算法则通过模拟鸟群觅食行为,更新粒子速度和位置以寻找最优解。
|
5月前
|
机器学习/深度学习 算法 Java
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
这篇文章介绍了基于贪婪技术思想的Prim算法和Dijkstra算法,包括它们的伪代码描述、Java源代码实现、时间效率分析,并展示了算法的测试用例结果,使读者对贪婪技术及其应用有了更深入的理解。
算法设计(动态规划应用实验报告)实现基于贪婪技术思想的Prim算法、Dijkstra算法
|
6月前
|
存储 传感器 算法
|
6月前
|
机器学习/深度学习 人工智能 算法
|
4天前
|
算法 数据安全/隐私保护
室内障碍物射线追踪算法matlab模拟仿真
### 简介 本项目展示了室内障碍物射线追踪算法在无线通信中的应用。通过Matlab 2022a实现,包含完整程序运行效果(无水印),支持增加发射点和室内墙壁设置。核心代码配有详细中文注释及操作视频。该算法基于几何光学原理,模拟信号在复杂室内环境中的传播路径与强度,涵盖场景建模、射线发射、传播及接收点场强计算等步骤,为无线网络规划提供重要依据。
|
17天前
|
机器学习/深度学习 算法
基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真
本项目基于改进遗传优化的BP神经网络进行金融序列预测,使用MATLAB2022A实现。通过对比BP神经网络、遗传优化BP神经网络及改进遗传优化BP神经网络,展示了三者的误差和预测曲线差异。核心程序结合遗传算法(GA)与BP神经网络,利用GA优化BP网络的初始权重和阈值,提高预测精度。GA通过选择、交叉、变异操作迭代优化,防止局部收敛,增强模型对金融市场复杂性和不确定性的适应能力。
152 80
|
5天前
|
机器学习/深度学习 数据采集 算法
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB2022a实现时间序列预测,采用CNN-GRU-SAM网络结构。卷积层提取局部特征,GRU层处理长期依赖,自注意力机制捕捉全局特征。完整代码含中文注释和操作视频,运行效果无水印展示。算法通过数据归一化、种群初始化、适应度计算、个体更新等步骤优化网络参数,最终输出预测结果。适用于金融市场、气象预报等领域。
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
|
5天前
|
算法
基于龙格库塔算法的锅炉单相受热管建模与matlab数值仿真
本设计基于龙格库塔算法对锅炉单相受热管进行建模与MATLAB数值仿真,简化为喷水减温器和末级过热器组合,考虑均匀传热及静态烟气处理。使用MATLAB2022A版本运行,展示自编与内置四阶龙格库塔法的精度对比及误差分析。模型涉及热传递和流体动力学原理,适用于优化锅炉效率。
|
3天前
|
移动开发 算法 计算机视觉
基于分块贝叶斯非局部均值优化(OBNLM)的图像去噪算法matlab仿真
本项目基于分块贝叶斯非局部均值优化(OBNLM)算法实现图像去噪,使用MATLAB2022A进行仿真。通过调整块大小和窗口大小等参数,研究其对去噪效果的影响。OBNLM结合了经典NLM算法与贝叶斯统计理论,利用块匹配和概率模型优化相似块的加权融合,提高去噪效率和保真度。实验展示了不同参数设置下的去噪结果,验证了算法的有效性。
|
2天前
|
算法 决策智能
基于SA模拟退火优化算法的TSP问题求解matlab仿真,并对比ACO蚁群优化算法
本项目基于MATLAB2022A,使用模拟退火(SA)和蚁群优化(ACO)算法求解旅行商问题(TSP),对比两者的仿真时间、收敛曲线及最短路径长度。SA源于金属退火过程,允许暂时接受较差解以跳出局部最优;ACO模仿蚂蚁信息素机制,通过正反馈发现最优路径。结果显示SA全局探索能力强,ACO在路径优化类问题中表现优异。