图的最小生成树算法: Prim算法和Kruskal算法(C++)

上一节我们学习了最短路径算法, 这一节来学习最小生成树.

最小生成树(Minimum Spanning Tree, MST)算法是图论中的一种重要算法, 主要用于在加权无向图中找到一棵生成树, 使得这棵树包含图中的所有顶点, 并且所有边的权重之和最小. 这样的树被称为最小生成树. 最小生成树广泛应用于网络设计, 电路布线等领域. 主要有两种算法 Prim 算法和 Kruskal 算法.


环境要求

本文所用样例在Windows 11以及Ubuntu 24.04上面编译通过.

  1. Windows: 使用[Visual Studio],
  2. Ubuntu: 使用 Clang 18.1.3. (Ubuntu 24.04 系统安装版本)
  3. GCC 无法编译直接本项目代码, 因为本文代码使用了 C++20 Module, 而 GCC 对此支持不完整.

关于 Module 的更多信息, 请参考我之前的博客: CMake 构建 C++20 Module 实例(使用 MSVC)

本项目工程目录: 图论代码


Prim 算法

Prim 算法是一种用于寻找加权无向图的最小生成树(Minimum Spanning Tree, MST)的经典贪心算法. 它由捷克数学家 Vojtěch Jarník 在 1930 年提出, 后来又被计算机科学家 Robert C. Prim 独立发现, 并因此得名. Prim 算法特别适用于稠密图, 即边的数量接近顶点数平方的情况.

算法步骤

Prim 算法的基本思想是从一个任意选择的起始顶点开始构建最小生成树, 逐步将距离当前生成树最近的顶点加入到生成树中, 直到所有顶点都被包含为止. 具体步骤如下:

  1. 初始化:

    • 选择任意一个顶点作为起始点, 将其标记为已访问.
    • 初始化一个优先队列(或最小堆), 用来存储尚未访问的顶点及其与当前生成树的最短距离. 初始时, 除了起始顶点外, 其他所有顶点的距离设为无穷大(表示还未连接).
  2. 迭代过程:

    • 从优先队列中取出距离当前生成树最近的顶点 u u u, 并将其标记为已访问.
    • 对于顶点 u u u 的所有邻接顶点 v v v, 如果 v v v 尚未被访问, 并且通过 u u u 到达 v v v 的距离比之前记录的距离更短, 则更新 v v v 的距离值, 并将( v v v, 距离)对插入或更新到优先队列中.
  3. 终止条件:

    • 当优先队列为空, 或者所有顶点都已被访问时, 算法结束. 此时, 已经找到了最小生成树.
伪代码
// 输入: 一个加权无向图G = (V, E), 其中V是顶点集合, E是边集合
// 输出: 最小生成树MST的边集Prim(G, start_vertex):// 初始化MST = []  // 存储最小生成树的边priority_queue = new MinHeap()  // 优先队列(最小堆), 存储(权重, 顶点)对visited = new Set()  // 已访问顶点集合add start_vertex to visited// 将起始顶点的所有邻接边加入优先队列for each neighbor in G.adjacent(start_vertex):if neighbor not in visited:priority_queue.insert((neighbor, weight(start_vertex, neighbor), start_vertex))// 主循环while not priority_queue.isEmpty():// 取出优先队列中权重最小的边(u, v)(u, weight_uv, previous_u) = priority_queue.extractMin()if u in visited:continue  // 如果顶点u已经被访问过, 则跳过// 将顶点u标记为已访问, 并将边(previous_u, u)加入MSTadd u to visitedadd (previous_u, u, weight_uv) to MST// 对于顶点u的所有邻接顶点vfor each (v, weight_u_v) in G.adjacent(u):if v not in visited:// 将(v, 权重)对插入或更新到优先队列中priority_queue.insertOrDecreaseKey((v, weight_u_v, u))return MST

样例

考虑下面这个图, 求它的最小生成树.

sample

  1. 初始化: 假设我们从G开始访问, 此时标记G为已访问, 并将与G相邻的点加入到优先队列中. 设置其他点的距离为无穷大.
    prim init

  2. 迭代过程:

  • 从优先队列中取出(G, C), 将C标记为已访问, 将G-C这条边加入到结果集中. 访问C的邻接点[A, B, D], 更新他们的距离, 由于新的距离更小, 所以将[A, B, D]加入优先队列中.
    prim c

  • 从优先队列中取出(C, A). 将A标记为已访问, 将C-A这条边加入到结果集中. 访问A的邻接点[B, C, D, H], 其中C已经访问过, 跳过. 将其他的边加入优先队列中.

    prim a

  • 从优先队列中取出(A, B). 将B标记为已访问, 将A-B这条边加入到结果集中. 访问B的邻接点[A, C, D, E], A, C均已访问, 跳过; 将其他的边加入优先队列中.
    prim b

  • 从优先队列中取出(B, E). 将E标记为已访问, 将B-E这条边加入到结果集中. 访问E的邻接点[B, D, F, H], B以访问,跳过. 将其他的边加入优先队列中.
    prim 3

  • 从优先队列中取出(B, D). 将D标记为已访问, 将B-D这条边加入到结果集中. 访问D的邻接点[A, B, C, E, F], 其中[A, B, C, E]已访问, 跳过. 将D,F加入优先队列.
    prim d

  • 跳过(C, B), (A,D) , (C,D)

  • 从优先队列中取出(D, F). 将F标记为已访问, 将D-F这条边加入到结果集中. 访问F的邻接点[D, E], 均已访问过, 跳过.
    prim f

  • 从优先队列中取出(G, H). 将H标记为已访问, 将G-H这条边加入到结果集中. 访问H的邻接点[A, E, G], 均已访问, 跳过.

    prim h

  • 其他边的顶点都已经访问过, 均被跳过, 算法结束. 得到的最小生成树如下:

ans

实现细节

typedef std::pair<unsigned, int> EdgeWithWeight;
class Prim {public:

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

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

相关文章

矩阵系统源码搭建的数据管理开发功能解析,支持OEM

一、引言 在矩阵系统中&#xff0c;数据犹如血液&#xff0c;贯穿整个系统的运行。高效的数据管理开发功能是确保矩阵系统稳定、可靠运行的关键&#xff0c;它涵盖了数据的存储、处理、安全等多个方面。本文将深入探讨矩阵系统源码搭建过程中数据管理功能的开发要点。 二、数据…

DeepSeek 助力 Vue 开发:打造丝滑的日期选择器(Date Picker),未使用第三方插件

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

操作系统知识点2

1.P&#xff0c;V操作可以实现进程同步&#xff0c;进程互斥&#xff0c;进程的前驱关系 2.先来先服务调度算法是不可抢占的算法 3.UNIX操作系统中&#xff0c;对文件系统中空闲区的管理通常采用成组链接法 4.对于FAT32文件系统&#xff0c;它采用的是链接结构 5.不同的I/O…

【个人开发】deepspeed+Llama-factory 本地数据多卡Lora微调【完整教程】

文章目录 1.背景2.微调方式2.1 关键环境版本信息2.2 步骤2.2.1 下载llama-factory2.2.2 准备数据集2.2.3 微调模式2.2.3.1 zero-1微调2.2.3.2 zero-2微调2.2.3.3 zero-3微调2.2.3.4 单卡Lora微调 2.2.4 实验2.2.4.1 实验1&#xff1a;多GPU微调-zero12.2.4.2 实验2&#xff1a;…

iOS 中使用 FFmpeg 进行音视频处理

在 iOS 中使用 FFmpeg 进行音视频处理,通常需要将 FFmpeg 的功能集成到项目中。由于 FFmpeg 是一个 C 库,直接在 iOS 中使用需要进行一些配置和封装。 1. 在 iOS 项目中集成 FFmpeg 方法 1:使用 FFmpeg 预编译库 下载 FFmpeg iOS 预编译库: 可以从以下项目中获取预编译的 …

Elasticsearch:将 Ollama 与推理 API 结合使用

作者&#xff1a;来自 Elastic Jeffrey Rengifo Ollama API 与 OpenAI API 兼容&#xff0c;因此将 Ollama 与 Elasticsearch 集成非常容易。 在本文中&#xff0c;我们将学习如何使用 Ollama 将本地模型连接到 Elasticsearch 推理模型&#xff0c;然后使用 Playground 向文档提…

openGauss 3.0 数据库在线实训课程18:学习视图管理

前提 我正在参加21天养成好习惯| 第二届openGauss每日一练活动 课程详见&#xff1a;openGauss 3.0.0数据库在线实训课程 学习目标 掌握openGauss视图的管理&#xff1a;创建视图、删除视图、查询视图的信息、修改视图的信息。 课程作业 1.创建表&#xff0c;创建普通视图…

腾讯云大模型知识引擎×DeepSeek赋能文旅

腾讯云大模型知识引擎DeepSeek赋能文旅 ——以合肥文旅为例的技术革新与实践路径 一、技术底座&#xff1a;知识引擎与DeepSeek的融合逻辑 腾讯云大模型知识引擎与DeepSeek模型的结合&#xff0c;本质上是**“知识库检索增强生成&#xff08;RAG&#xff09;实时联网能力”**…

利用SkinMagic美化MFC应用界面

MFC(Microsoft Foundation Class)应用程序的界面设计风格通常比较保守,而且虽然MFC框架的控件功能强大且易于集成,但视觉效果较为朴素,缺乏现代感。尤其是MFC应用程序的设计往往以功能实现为核心,界面设计可能显得较为简洁甚至略显呆板,用户体验可能不如现代应用程序流畅…

qt QOpenGLTexture详解

1. 概述 QOpenGLTexture 是 Qt5 提供的一个类&#xff0c;用于表示和管理 OpenGL 纹理。它封装了 OpenGL 纹理的创建、分配存储、绑定和设置像素数据等操作&#xff0c;简化了 OpenGL 纹理的使用。 2. 重要函数 构造函数&#xff1a; QOpenGLTexture(const QImage &image,…

nlp|微调大语言模型初探索(2),训练自己的聊天机器人

前言 上篇文章记录了具体的微调语言大模型步骤&#xff0c;以及在微调过程中可能遇见的各种报错&#xff0c;美中不足的是只是基于开源数据集的微调&#xff0c;今天来记录一下怎么基于自己的数据集去微调大语言模型&#xff0c;训练自己的智能机器人&#xff01;&#xff01;&…

Java 大视界 -- 量子计算时代 Java 大数据的潜在变革与应对策略(88)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

手机功耗BugReport字段含义介绍

BugReport一般用来分析功耗问题&#xff0c;例如休眠待机&#xff0c;后台待机&#xff0c;游戏&#xff0c;视频&#xff0c;相机场景等 BugReport字段含义介绍 BugReport字段 含义 备注 Reboot 设备的重启事件 CPU running CPU运行状态&#xff0c;休眠 或者 唤醒 只有…

什么是 近端策略优化算法PPO

什么是 近端策略优化算法PPO 近端策略优化算法(Proximal Policy Optimization,PPO)是OpenAI公司于2017年开发的一系列无模型强化学习算法,用于优化策略网络以最大化累计奖励。以下是具体介绍及示例: 算法原理 策略梯度:PPO基于策略梯度算法,通过估计策略网络的梯度来更…

计算机视觉-局部特征

一、局部特征 1.1全景拼接 先用RANSAC估计出变换&#xff0c;就可以拼接两张图片 ①提取特征 ②匹配特征 ③拼接图像 1.2 点的特征 怎么找到对应点&#xff1f;&#xff08;才能做点对应关系RANSAC&#xff09; &#xff1a;特征检测 我们希望找到的点具有的特征有什么特…

个人搭建CDN加速服务 特网科技

在互联网快速发展的今天&#xff0c;网站的加载速度对用户体验有着至关重要的影响&#xff0c;传统的网页加载方式依赖于服务器的性能和网络环境&#xff0c;这使得某些网站的页面加载时间过长&#xff0c;用户体验不佳&#xff0c;为了解决这个问题&#xff0c;许多企业开始采…

类型通配符上限

主函数 package typeWildcardTop;import java.util.ArrayList;public class typeWildcardTopTest {/**/public static void main(String[] args) { // test1();test2();}/*测试showList接收ArrayList类型 ArrayList接收各种类型参数创建animals cats mincats集合 传入s…

OpenCV(1):简介、安装、入门案例、基础模块

1 OpenCV 简介 OpenCV 是一个功能强大、应用广泛的计算机视觉库&#xff0c;它为开发人员提供了丰富的工具和算法&#xff0c;可以帮助他们快速构建各种视觉应用。随着计算机视觉技术的不断发展&#xff0c;OpenCV 也将会继续发挥重要的作用。OpenCV 提供了大量的计算机视觉算法…

FTP自动上传/vue打包自动上传

ftp自动上传 在我们平时开发项目时&#xff0c;需要将本地代码编译后上传到服务器&#xff0c;我们可以借助Node.js库中的ssh2来实现自动上传 首先我们先来说下ssh2的安装和使用 安装ssh2 npm install ssh2创建ssh2实例 const { Client } require(ssh2);连接服务器 const c…

SQL复习

SQL复习 MySQL SQL介绍 SQL SQL的全拼是什么&#xff1f; SQL全拼&#xff1a;Structured Query Language&#xff0c;也叫结构化查询语言。 SQL92和SQL99有什么区别呢&#xff1f; SQL92和SQL99分别代表了92年和99年颁布的SQL标准。 在 SQL92 中采用&#xff08;&#xff…