【算法】最小生成树——普利姆 (Prim) 算法

目录

  • 1.概述
  • 2.代码实现
    • 2.1.邻接矩阵存储图
    • 2.2.邻接表存储图
    • 2.3.测试
  • 3.应用

1.概述

(1)在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边,而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集且为无循环图,使得联通所有结点w(T) 最小,则此 T 为 G 的最小生成树 (minimal spanning tree)

(2)普利姆 (Prim) 算法是一种用于解决最小生成树问题的贪心算法,其主要思路如下:

  • ① 选择任意一个顶点作为起始点,将其加入最小生成树中。
  • ② 从已选择的顶点集合中选取一个顶点,该顶点与未选择的顶点构成的边权重最小,并且该边的另一端顶点未被选择,将该顶点和边加入最小生成树中。
  • ③ 重复步骤 ②,直到最小生成树包含了图中的所有顶点。

(3)例如,对带权连通无向图 G 使用普利姆 (Prim) 算法构造最小生成树的过程如下:

请添加图片描述

另外一种生成最小生成树的克鲁斯卡尔 (Kruskal) 算法可参考【算法】最小生成树——克鲁斯卡尔 (Kruskal) 算法这篇文章。

2.代码实现

2.1.邻接矩阵存储图

class Solution {// INF 表示两点之间没有连接,即无穷大int INF = Integer.MAX_VALUE;/*graph: 用于表示图的邻接矩阵返回值: 路径矩阵*/public int prim(int[][] graph) {//图中的顶点数int V = graph.length;// weight[i] 表示从 i 点到已访问集合的最小边权值int[] weight = new int[V];Arrays.fill(weight, INF);//标记节点是否在最小生成树中boolean[] mstSet = new boolean[V];// parent[i] 表示从 i 点到最小生成树的一条边int[] parent = new int[V];//从顶点 0 开始生成最小树weight[0] = 0;//根节点没有父节点parent[0] = -1;//访问 V - 1 个节点for (int i = 0; i < V - 1; i++) {//从未访问的节点中选择 weight 最小的节点 uint u = minKey(weight, mstSet);//将节点 u 标记为已访问mstSet[u] = true;//访问与 u 相邻的节点 vfor (int v = 0; v < V; v++) {//如果 v 未被访问过、u - v 之间有边、并且 u - v 之间的距离比原本的距离小if (!mstSet[v] && graph[u][v] != 0 && graph[u][v] != INF && graph[u][v] < weight[v]) {//将 u - v 之间的边加入最小生成树parent[v] = u;//标记从 v 到已访问集合的最小边权值weight[v] = graph[u][v];}}}//计算最小生成树的权值并返回int sum = 0;for (int i = 1; i < V; i++) {sum += weight[i];}//输出最小生成树的路径System.out.println("最小生成树的路径以及对应的权重依次为: ");for (int i = 1; i < V; i++) {System.out.println("(" + parent[i] + "-" + i + ") " + weight[i]);}return sum;}public int minKey(int[] weight, boolean[] mstSet) {//初始化 weight 的最小值和对应的节点int min = INF;int minIndex = -1;for (int v = 0; v < weight.length; v++) {//如果 v 节点未被访问,并且 v 节点到已访问集合的边的权值更小if (!mstSet[v] && weight[v] < min) {//更新最小值min = weight[v];//更新 weight 的最小值对应的节点minIndex = v;}}return minIndex;}
}

2.2.邻接表存储图

class Solution {// INF 表示两点之间没有连接,即无穷大int INF = Integer.MAX_VALUE;/*graph: 用于表示图的邻接表返回值: 最小生成树的权重*/public int prim(List<int[]>[] graph) {//图中的顶点数int V = graph.length;// weight[i] 表示从 i 点到已访问集合的最小边权值int[] weight = new int[V];Arrays.fill(weight, INF);//标记节点是否在最小生成树中boolean[] mstSet = new boolean[V];// parent[i] 表示从 i 点到最小生成树的一条边int[] parent = new int[V];//从顶点 0 开始生成最小树weight[0] = 0;//根节点没有父节点parent[0] = -1;//访问 V - 1 个节点for (int i = 0; i < V - 1; i++) {//从未访问的节点中选择 weight 最小的节点 uint u = minKey(weight, mstSet);//将节点 u 标记为已访问mstSet[u] = true;//访问与 u 相邻的节点 vfor (int[] node : graph[u]) {int v = node[0];int w = node[1];if (!mstSet[v] && w < weight[v]) {parent[v] = u;weight[v] = w;}}}//计算最小生成树的权值并返回int sum = 0;for (int i = 1; i < V; i++) {sum += weight[i];}//输出最小生成树的路径System.out.println("最小生成树的路径以及对应的权重依次为: ");for (int i = 1; i < V; i++) {System.out.println("(" + parent[i] + "-" + i + ") " + weight[i]);}return sum;}public int minKey(int[] weight, boolean[] mstSet) {//初始化 weight 的最小值和对应的节点int min = INF;int minIndex = -1;for (int v = 0; v < weight.length; v++) {//如果 v 节点未被访问,并且 v 节点到已访问集合的边的权值更小if (!mstSet[v] && weight[v] < min) {//更新最小值min = weight[v];//更新 weight 的最小值对应的节点minIndex = v;}}return minIndex;}
}

2.3.测试

(1)本测试中的加权无向图如下所示:

在这里插入图片描述

(2)邻接矩阵的测试代码如下:

class Test {public static void main(String[] args) {//图的顶点数int n = 7;int[][] graph = new int[n][n];//初始化邻接矩阵,初始化为 Integer.MAX_VALUE 表示不可达for (int i = 0; i < n; i++) {Arrays.fill(graph[i], Integer.MAX_VALUE);graph[i][i] = 0;}//添加图的边graph[0][1] = 9;graph[0][5] = 1;graph[1][0] = 9;graph[1][2] = 4;graph[1][6] = 3;graph[2][1] = 4;graph[2][3] = 2;graph[3][2] = 2;graph[3][4] = 6;graph[3][6] = 5;graph[4][3] = 6;graph[4][5] = 8;graph[4][6] = 7;graph[5][0] = 1;graph[5][4] = 8;graph[6][1] = 3;graph[6][3] = 5;graph[6][4] = 7;Solution solution = new Solution();int sum = solution.prim(graph);System.out.println("最小生成树的权重为: " + sum);}
}

输出结果如下:

最小生成树的路径以及对应的权重依次为: 
(2-1) 4
(3-2) 2
(4-3) 6
(5-4) 8
(0-5) 1
(1-6) 3
最小生成树的权重为: 24

(3)邻接表的测试代码如下:

class Test {public static void main(String[] args) {//图的顶点数int n = 7;List<int[]>[] graph = new ArrayList[n];//初始化邻接表for (int i = 0; i < n; i++) {graph[i] = new ArrayList<>();}//添加图的边graph[0].add(new int[]{1, 9});graph[0].add(new int[]{5, 1});graph[1].add(new int[]{0, 9});graph[1].add(new int[]{2, 4});graph[1].add(new int[]{6, 3});graph[2].add(new int[]{1, 4});graph[2].add(new int[]{3, 2});graph[3].add(new int[]{2, 2});graph[3].add(new int[]{4, 6});graph[3].add(new int[]{6, 5});graph[4].add(new int[]{3, 6});graph[4].add(new int[]{5, 8});graph[4].add(new int[]{6, 7});graph[5].add(new int[]{0, 1});graph[5].add(new int[]{4, 8});graph[6].add(new int[]{1, 3});graph[6].add(new int[]{3, 5});graph[6].add(new int[]{4, 7});Solution solution = new Solution();int sum = solution.prim(graph);System.out.println("最小生成树的权重为: " + sum);}
}

输出结果如下:

最小生成树的路径以及对应的权重依次为: 
(2-1) 4
(3-2) 2
(4-3) 6
(5-4) 8
(0-5) 1
(1-6) 3
最小生成树的权重为: 24

3.应用

(1)求图的最小生成树许多实际应用,例如城市之间的交通工程造价最优问题就是一个最小生成树问题。

(2)大家可以去 LeetCode 上找相关的最小生成树的题目来练习,或者也可以直接查看 LeetCode 算法刷题目录 (Java) 这篇文章中的最小生成树章节。如果大家发现文章中的错误之处,可在评论区中指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/155586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

湖科大计网:应用层

一、应用层概述 交互&#xff0c;实现特定问题&#xff01; 二、客户与服务器模型 一、C/S 客户/服务器方式 服务与被服务的关系。 二、P2P方式 对等方式 P2P方式是对等的&#xff0c;没有固定的服务器。 三、DNS域名系统 DNS&#xff08;Domain Name System&#xff09; 一、域…

2018年计网408

第33题 下列 TCP/P应用层协议中, 可以使用传输层无连接服务的是()A. FTPB. DNSC. SMTPD. HTTP 本题考察TCP/IP体系结构中&#xff0c;应用层常用协议所使用的运输层服务。 如图所示。这是TCP/IP体系结构中常见应用层协议各自所使用的运输层端口,。在这些应用层协议中&#x…

Vue Router的使用

Vue.js是一个流行的JavaScript框架&#xff0c;用于开发单页面应用程序。Vue提供了一个强大的路由系统&#xff0c;可以帮助我们管理应用程序中的不同页面。在本文中&#xff0c;我们将详细讲解Vue路由的使用方法。 目录 1. 安装Vue Router2. 创建路由实例3. 配置路由4. 在模板…

关闭bitlocker加密

windows11的笔记本电脑买回来发现分驱都处于bitlocker状态&#xff0c;上网上搜索都是说进入控制面板的安全项进行关闭&#xff0c;包括去搜索栏搜索“管理 BitLocker”&#xff0c;对搜索出来的项打开&#xff0c;经过试验&#xff0c;它们进入的是同一个位置&#xff0c;只有…

【docker】虚拟化和docker容器概念

基础了解 IAAS&#xff1a; 基础设施服务&#xff0c;&#xff08;只提供基础设施&#xff0c;没有系统&#xff09; **SAAS&#xff1a; ** 软件即服务&#xff0c;&#xff08;提供基础设施和系统&#xff09; PAAS&#xff1a; 平台即服务&#xff0c;&#xff08;提供基…

SwiftUI 如何动态开始和停止播放永久重复(repeatForever)动画

0. 功能需求 在 SwiftUI 丰富多彩的动画世界中,我们有时希望可以随意开始和停止永久循环(repeatForever)的动画,不过这时往往会产生错误的动画“叠加”效果。 从上图可以看到:虽然我们希望密码输入框背景只在用户输入密码时才发生闪烁,但顶部的密码输入框随着不断输入其…

Linux02 VIM编辑器

Linux02 VIM编辑器 基本上 vi/vim 共分为三种模式&#xff0c; 分别是命令模式&#xff08;Command mode&#xff09;&#xff0c;输入模式&#xff08;Insert mode&#xff09;和底线命令模式&#xff08;Last line mode&#xff09;。 三种状态进行切换 插入模式&#xff1a…

Java入门篇 之 内部类

本篇碎碎念&#xff1a;本篇没有碎碎念&#xff0c;想分享一段话&#xff1a; 你不笨&#xff0c;你只是需要时间&#xff0c;耐心就是智慧&#xff0c;不见得快就好&#xff0c;如果方向都不对&#xff0c;如果心术不正&#xff0c;如果德不配位&#xff0c;快就是对自己天分的…

【数值计算方法】矩阵特征值与特征向量的计算(一):Jacobi 旋转法及其Python实现

文章目录 一、Jacobi 旋转法1. 基本思想2. 计算过程演示3. 注意事项 二、Python实现迭代过程&#xff08;调试&#xff09; 矩阵的特征值&#xff08;eigenvalue&#xff09;和特征向量&#xff08;eigenvector&#xff09;在很多应用中都具有重要的数学和物理意义。Jacobi 旋转…

六、流量监管、流量整形

流量监管、流量整形 流量监管、流量整形1.1.定义1.2.简单流分类应用场景举例1.3.简单流分类的配置1.4.复杂流分类1.5.复杂流分类在产品中的实现 ————————————————— 流量监管、流量整形 当报文的发送速率大于接收速率&#xff0c;或者下游设备的接口速率小于…

GitHub 2023报告-开源和AI的现状

GitHub 2023报告-开源和AI的现状 深入探讨人工智能如何与开源互动&#xff0c;以及未来几年可能出现的趋势。 背景介绍 2023年&#xff0c;开源已成为全球软件开发的标准。无论是大公司还是小团队&#xff0c;都广泛使用开源技术进行项目开发。此外&#xff0c;随着机器学习和…

【Java】java | CacheManager | redisCacheManager

一、说明 1、查询增加缓存&#xff0c;使用Cacheable注解 2、项目中已经用到了ehcache&#xff0c;现在需求是两个都用 二、备份配置 1、redisConfig增加代码 Bean("redisCacheManage")Primarypublic CacheManager redisCacheManager(RedisConnectionFactory fact…

CKD TransBTS:用于脑肿瘤分割的具有模态相关交叉注意的临床知识驱动混合转换器

CKD-TransBTS: Clinical Knowledge-Driven Hybrid Transformer With Modality-Correlated Cross-Attention for Brain Tumor Segmentation CKD TransBTS&#xff1a;用于脑肿瘤分割的具有模态相关交叉注意的临床知识驱动混合转换器背景贡献实验方法how radiologists diagnose b…

【19年扬大真题】已知a数组int a[ ]={1,2,3,4,5,6,7,8,9,10},编写程序,求a数组中偶数的个数和偶数的平均值

【18年扬大真题】 已知a数组int a[ ]{1,2,3,4,5,6,7,8,9,10}&#xff0c;编写程序&#xff0c;求a数组中偶数的个数和偶数的平均值 int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int os 0;//偶数个数int sum 0;//偶数和float ave 0;//偶数平均值for (int i 0;i <…

关于2023年11月25日PMI认证考试准考信下载及考场规定等事项通知

各位考生&#xff1a;为保证参加2023年11月25日PMI项目管理资格认证考试的每位考生都能顺利进入考场参加考试&#xff0c;请完整阅读本通知内容。 一、关于准考信下载为确保您顺利进入考场参加11月份考试&#xff0c;请及时登录本网站个人系统下载并打印准考信&#xff0c;准考…

Google codelab WebGPU入门教程源码<6> - 使用计算着色器实现计算元胞自动机之生命游戏模拟过程(源码)

对应的教程文章: https://codelabs.developers.google.com/your-first-webgpu-app?hlzh-cn#7 对应的源码执行效果: 对应的教程源码: 此处源码和教程本身提供的部分代码可能存在一点差异。点击画面&#xff0c;切换效果。 class Color4 {r: number;g: number;b: number;a…

论文阅读:“基于特征检测与深度特征描述的点云粗对齐算法”

文章目录 摘要简介相关工作粗对齐传统的粗对齐算法基于深度学习的粗对齐算法 特征检测及描述符构建 本文算法ISS 特征检测RANSAC 算法3DMatch 算法 实验结果参考文献 摘要 点云对齐是点云数据处理的重要步骤之一&#xff0c;粗对齐则是其中的难点。近年来&#xff0c;基于深度…

【机器学习Python实战】线性回归

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习python实战 欢迎订阅&#xff01;后面的内容会越来越有意思~ ⭐内容说明&#xff1a;本专栏主要针对机器学习专栏的基础内容进行python的实现&#xff0c;部分…

C++ Qt 学习(十):Qt 其他技巧

1. 带参数启动外部进程 QProcess 用于启动外部进程int QProcess::execute(const QString &program, const QStringList &arguments);QObject *parent; ... QString program "./path/to/Qt/examples/widgets/analogclock"; QStringList arguments; argument…

当前系统并无桌面环境,或无显示器,无法显示远程桌面,您需要自行安装X11桌面环境,或者使用终端文件功能

ToDesk远程遇到的问题如上图&#xff0c;换向日葵直接黑屏&#xff1b; 问题原因 截止发文时间&#xff0c;Todesk只支持X11协议&#xff0c;没有适配最新的Wayland协议&#xff0c;所以我们需要把窗口系统调整为X11才可以。 解决方法 修改配置文件&#xff0c;关闭wayland su…