Prim 最小生成树算法(MST)

Prim算法是贪婪算法,类似于Kruskal算法。该算法始终从单个节点出发,经过多个相邻节点,以探索沿途所有连接的边。

该算法从一个空生成树开始。
其理念是维持两组顶点。第一组包含已包含在MST中的顶点,另一组包含尚未包含的顶点。
每一步,它都会考虑连接这两个集合的所有边,并从这些边中选择最小权重边。选定边后,将边的另一端点移动到包含MST的集合。

普里姆算法的工作原理
确定一个任意顶点作为MST的起始顶点。我们在上图中选择0。
按照步骤3到5,直到出现不包含在MST中的顶点(称为边缘顶点)。
找到连接任意树顶点与边缘顶点的边。
在这些边中找出最小值。
将选定的边添加到MST中。由于我们只考虑连接边缘顶点与其余边的边,因此从未得到一个环。
归还MST并离开
邻接矩阵表示的简单实现
按照上述步骤,利用上述Prim算法来求图的MST:

创建一个集合mstSet,跟踪MST中已包含的顶点。
为输入图中的所有顶点分配一个关键值。将所有键值初始化为无限。将第一个顶点的键值指定为0,这样它会被优先选中。
虽然mstSet不包含所有顶点
=> 选择一个mstSet 中不存在且有最小键值的顶点u。
=> 将u包含在mstSet中。
=> 更新 u 所有相邻顶点的键值。要更新键值,遍历所有相邻顶点。对于每个相邻顶点 v,如果边 u-v 的权重小于 v 的前一个键值,则将键值更新为 u-v 的权重。
使用关键值的目的是从切割中选择最小权重边。键值仅用于尚未包含在MST中的顶点,这些顶点的键值表示连接它们与MST中顶点集合的最小权重边。

import java.io.*; import java.lang.*; import java.util.*; class MST { // A utility function to find the vertex with minimum // key value, from the set of vertices not yet included // in MST int minKey(int key[], Boolean mstSet[]) { // Initialize min value int min = Integer.MAX_VALUE, min_index = -1; for (int v = 0; v < mstSet.length; v++) if (mstSet[v] == false && key[v] < min) { min = key[v]; min_index = v; } return min_index; } // A utility function to print the constructed MST // stored in parent[] void printMST(int parent[], int graph[][]) { System.out.println("Edge \tWeight"); for (int i = 1; i < graph.length; i++) System.out.println(parent[i] + " - " + i + "\t" + graph[parent[i]][i]); } // Function to construct and print MST for a graph // represented using adjacency matrix representation void primMST(int graph[][]) { int V = graph.length; // Array to store constructed MST int parent[] = new int[V]; // Key values used to pick minimum weight edge in // cut int key[] = new int[V]; // To represent set of vertices included in MST Boolean mstSet[] = new Boolean[V]; // Initialize all keys as INFINITE for (int i = 0; i < V; i++) { key[i] = Integer.MAX_VALUE; mstSet[i] = false; } // Always include first 1st vertex in MST. // Make key 0 so that this vertex is // picked as first vertex key[0] = 0; // First node is always root of MST parent[0] = -1; // The MST will have V vertices for (int count = 0; count < V - 1; count++) { // Pick the minimum key vertex from the set of // vertices not yet included in MST int u = minKey(key, mstSet); // Add the picked vertex to the MST Set mstSet[u] = true; // Update key value and parent index of the // adjacent vertices of the picked vertex. // Consider only those vertices which are not // yet included in MST for (int v = 0; v < V; v++) // graph[u][v] is non zero only for adjacent // vertices of m mstSet[v] is false for // vertices not yet included in MST Update // the key only if graph[u][v] is smaller // than key[v] if (graph[u][v] != 0 && mstSet[v] == false && graph[u][v] < key[v]) { parent[v] = u; key[v] = graph[u][v]; } } // Print the constructed MST printMST(parent, graph); } public static void main(String[] args) { MST t = new MST(); int graph[][] = new int[][] { { 0, 2, 0, 6, 0 }, { 2, 0, 3, 8, 5 }, { 0, 3, 0, 0, 7 }, { 6, 8, 0, 0, 9 }, { 0, 5, 7, 9, 0 } }; // Print the solution t.primMST(graph); } }

输出
Edge Weight
0 - 1 2
1 - 2 3
0 - 3 6
1 - 4 5
时间复杂度:O(V2由于我们使用邻接矩阵,如果输入图用邻接列表表示,那么借助二元堆,Prim算法的时间复杂度可以简化为O((E+V) * logV)。
辅助空间:O(V)

使用优先队列和邻接列表的高效实现
对于邻接列表表示,我们可以实现 O(((E+V)*log(V)),因为我们可以在 O(V + E) 时间内找到每个顶点的所有相邻,并且在 O(Log V) 时间内通过优先队列获得最小值。

我们使用优先队列(最小堆)来始终选择权重最小的边。
将第一个顶点及其权重推入队列。
当队列不空时,提取最小权重边。
如果顶点未被访问,将其权重加到变量(res)上,并标记为已访问。
将该顶点所有未访问的相邻顶点推入队列。
处理完所有顶点后,返回以 res(分辨率)存储的总权重。

import java.util.PriorityQueue; import java.util.ArrayList; class GFG { // Returns total weight of the Minimum Spanning Tree static int spanningTree(int V, ArrayList<ArrayList<int[]>> adj) { // Min-heap storing {weight, vertex} PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]); boolean[] visited = new boolean[V]; int res = 0; // Start from node 0 pq.add(new int[]{0, 0}); while(!pq.isEmpty()) { int[] p = pq.poll(); int wt = p[0]; int u = p[1]; if(visited[u]) continue; res += wt; visited[u] = true; // Push adjacent edges for(int[] v : adj.get(u)) { if(!visited[v[0]]) { pq.add(new int[]{v[1], v[0]}); } } } return res; } public static void main(String[] args) { int V = 3; ArrayList<ArrayList<int[]>> adj = new ArrayList<>(); for(int i = 0; i < V; i++) adj.add(new ArrayList<>()); adj.get(0).add(new int[]{1, 5}); adj.get(1).add(new int[]{0, 5}); adj.get(1).add(new int[]{2, 3}); adj.get(2).add(new int[]{1, 3}); adj.get(0).add(new int[]{2, 1}); adj.get(2).add(new int[]{0, 1}); System.out.println(spanningTree(V, adj)); } }

输出
4
时间复杂度:O(((E+V)*log(V)),其中V是顶点数,E是边数。
辅助空间:O(E+V),其中V是顶点数,E是边数

它是如何运作的?
核心基于MST的一个基本性质,称为割性质(如果我们将顶点划分为两组(即割),那么穿越该割的最轻边必须是图中某个MST的一部分。由于我们总是考虑割顶点,因此从不形成循环。

Prim算法的优缺点
优势:

Prim算法保证能在连通加权图中找到MST。
使用二元堆或斐波那契堆时,其时间复杂度为 O((E+V)×log(V)),其中 E 是边数,V 是顶点数。
与其他一些MST算法相比,它是一个相对简单易懂和实现的算法。
缺点:

与Kruskal算法类似,Prim算法在多边密集图上可能较慢,因为它需要至少遍历所有边一次。
Prim算法依赖优先级队列,这会占用额外内存,并在非常大的图中使算法变慢。
起始节点的选择会影响MST输出,这在某些应用中可能并不理想。

编程资源 https://pan.quark.cn/s/7f7c83756948 更多资源 https://pan.quark.cn/s/bda57957c548

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

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

相关文章

全球物流业进入“退货季“,女士连衣裙退货率接近90%

、美通社消息&#xff1a;随着年终购物旺季的结束&#xff0c;全球物流业已进入"退货季"。当前&#xff0c;电商供应链中的退货环节正扮演着日益关键的角色。过去几年间&#xff0c;退货已从后台的成本中心转变为一线的战略差异化因素。基于DHL《2025电子商务趋势报告…

vivado2023.2安装步骤详解:FPGA开发环境从零搭建

以下是对您提供的博文内容进行深度润色与结构重构后的技术文章。本次优化严格遵循您的全部要求&#xff1a;✅ 彻底去除AI痕迹&#xff0c;语言自然、专业、有“人味”&#xff1b;✅ 摒弃模板化标题&#xff08;如“引言”“总结”&#xff09;&#xff0c;代之以逻辑递进、场…

超详细版MOSFET开关时序分析及其工作原理

深入MOSFET的“心跳”&#xff1a;开关时序与动态行为全解析你有没有想过&#xff0c;一个看似简单的“开”和“关”&#xff0c;背后竟藏着如此复杂的物理过程&#xff1f;在现代电源设计中&#xff0c;MOSFET早已不是那个教科书里一句话就能讲完的“电压控制开关”。当我们把…

有没有推荐的汽车自动化生产系统或智能解决方案?

在汽车制造这个行当里&#xff0c;自动化正在悄悄经历一场本质的蜕变。早年间&#xff0c;我们谈论的还只是机械臂按固定程序焊接、喷涂、搬运——机器固然高效&#xff0c;但说到底&#xff0c;只是听令行事的“工具”。而如今&#xff0c;情况不一样了。随着AI、物联网和数字…

深度剖析树莓派apt-update出错的根源与修复方法

树莓派apt update总失败&#xff1f;一文讲透根源与实战修复你有没有遇到过这样的场景&#xff1a;刚插上树莓派&#xff0c;连好网络&#xff0c;信心满满地敲下那句经典的&#xff1a;sudo apt update结果终端却报出一堆红字错误——连接超时、密钥缺失、域名无法解析……原本…

污水流量监测之多普勒超声波流量计应用技术分析

一&#xff0e;引文在水污染防治与水资源管理体系中&#xff0c;污水流量数据的精准获取是开展污染物总量控制、污水处理工艺优化、水环境质量评估的核心前提。多普勒超声波流量计作为一种接触式流量测量设备&#xff0c;凭借其抗干扰能力强、适应复杂工况的技术特性&#xff0…

深度剖析LED驱动电路启动过程与响应特性

深度剖析LED驱动电路启动过程与响应特性&#xff1a;从原理到实战的系统性解读一场“看不见的战役”——LED上电瞬间究竟发生了什么&#xff1f;你有没有注意过&#xff0c;当你打开一盏LED台灯时&#xff0c;它几乎是“即开即亮”&#xff0c;毫无延迟。而某些廉价灯具却会先闪…

回首 jQuery 20 年:从辉煌到没落

2006 年 1 月 14 日&#xff0c;John Resig 发布了名为 jQuery 的 JavaScript 库。 至今已经过去了 20 年&#xff01; 20 周年之际&#xff0c;jQuery 4.0 正式发布了&#xff01; 是的&#xff0c;就是那个被无数人宣布“已死”的 jQuery&#xff0c;经过 10 年的等待后迎…

汇编语言全接触-100.拾取密码框中的密码

概述&#xff1a;其实早有所闻 Windows 的马虎&#xff0c;Windows打星号的密码框中的密码实际上是很容易得到的&#xff0c;我以前看到过的资料说是检索屏幕上的窗口&#xff0c;找到有 ES_PASSWORD 风格的就向它发送取消 ES_PASSWORD 的消息&#xff0c;然后刷新它&#xff0…

拒绝尬聊死循环:开发者视角下的“社交冷启动”算法优化

为什么你的社交“冷启动”总是 Timeout&#xff1f;做开发的同学都知道&#xff0c;系统初始化最怕的就是死循环。很多兄弟在面对刚加上的微信好友时&#xff0c;聊天逻辑极其简陋&#xff1a;While(true) { Send("在吗"); Wait(86400); }这种低效的请求不仅拿不到正…

ARM体系结构

一、嵌入式系统的本质与层级嵌入式系统的官方定义是&#xff1a;以应用为中心&#xff0c;以计算机技术为基础&#xff0c;软硬件可剪裁的专用计算机系统。它与通用计算机最大的不同&#xff0c;在于完全围绕具体应用场景设计&#xff0c;可根据需求对功耗、体积、环境适应性、…

RPA 自动化推送中的多任务调度与并发控制

​ QiWe开放平台 个人名片 API驱动企微自动化&#xff0c;让开发更高效 核心能力&#xff1a;为开发者提供标准化接口、快速集成工具&#xff0c;助力产品高效拓展功能场景 官方站点&#xff1a;https://www.qiweapi.com 团队定位&#xff1a;专注企微API生态…

opencv基础(轮廓检测、绘制与特征)

一、轮廓检测轮廓定义&#xff1a;图像中具有相同颜色 / 灰度的连续像素点连接形成的闭合曲线&#xff0c;代表前景与背景的边界&#xff0c;与边缘&#xff08;单像素灰度突变&#xff09;不同&#xff0c;轮廓更强调整体外形与连通性。cv2.findContours 是 OpenCV 用于从二值…

Leetcode—3314. 构造最小位运算数组 I【简单】

2025每日刷题&#xff08;240&#xff09; Leetcode—3314. 构造最小位运算数组 I实现代码 func minBitwiseArray(nums []int) []int {ans : make([]int, 0)for _, x : range nums {if x 2 {ans append(ans, -1)} else {for i : 1; i < 32; i {if x >> i & 1 0…

集成运放加法器电路原理验证的实战案例(含Multisim仿真)

以下是对您提供的博文内容进行 深度润色与结构重构后的技术博客正文 。本次优化严格遵循您的全部要求&#xff1a; ✅ 彻底去除AI痕迹&#xff0c;语言自然、专业、有“人味”&#xff1b; ✅ 打破模板化标题体系&#xff0c;以逻辑流驱动章节演进&#xff1b; ✅ 将原理、…

词根词缀拆解|dict- = 说/断言!用兜兜英语快速记牢高频词

喽英语学习者们&#x1f44b;&#xff01;今天用「兜兜英语词根词缀拆解工具」带大家吃透一个超实用前缀——dict-&#xff0c;它的核心含义是「说、断言」&#xff0c;衍生出的单词遍布阅读、写作、口语场景&#xff0c;掌握它能批量解锁高频词&#xff0c;记忆效率直接翻倍✨…

基于多目标粒子群优化算法的冷热电联供型综合能源系统运行优化(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1…

计算机毕业设计springboot少儿编程教培机构教务管理系统 基于SpringBoot的青少年编程培训中心教务运营平台 少儿编程教育机构教学事务一体化管理系统

计算机毕业设计springboot少儿编程教培机构教务管理系统g0q16b8i &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。当“双减”把学科类培训推向边缘&#xff0c;编程却凭借信息学奥…

‌如何测试AI的“推理深度”?我设计了“五层追问”测试

五层追问不是提问技巧&#xff0c;而是一套可度量、可复用的AI推理测试框架‌ 在AI辅助测试用例生成、缺陷根因分析、自动化决策等场景中&#xff0c;AI的“推理深度”直接决定测试质量的下限。传统评估仅关注输出结果是否正确&#xff0c;而‌“五层追问”测试法‌通过结构化…

GC-IP201 驱动

数据手册官网上面 https://amac-chemnitz.com/index.php/en/products/interpolationsschaltkreise/93-gc-ip201b-en STM32F103C8T6翻译后的是通信协议&#xff1a;每个数据传输都通过主机处理器发送一个SPI字来启动。一个SPI字由4位操作码、4位硬件地址和最多8位数据组成。 只有…