新闻中心

C++如何实现一个最小生成树算法_C++图论之Prim与Kruskal算法详解

2025-11-21
浏览次数:
返回列表
Prim算法从点出发,每次选最近顶点加入生成树,适合稠密图;Kruskal按边权排序贪心选取,用并查集判环,适合稀疏图;两者时间复杂度分别为O(V²)和O(E log E),应根据图的密度选择。

c++如何实现一个最小生成树算法_c++图论之prim与kruskal算法详解

在图论中,最小生成树(Minimum Spanning Tree, MST)是连接无向连通图中所有顶点的一棵树,且边的权值总和最小。C++中常用的两种求解MST的算法是Prim算法Kruskal算法。下面详细介绍它们的原理与实现方式。

Prim算法:从点出发构建最小生成树

Prim算法的核心思想是从一个起始顶点开始,逐步扩展生成树,每次选择与当前生成树相连且权值最小的边所连接的新顶点,直到覆盖所有顶点。

适用场景:稠密图(边数接近顶点数平方),使用邻接矩阵存储更高效。

Prim算法步骤:

  • 初始化一个布尔数组visited标记顶点是否已加入生成树,距离数组dist记录各顶点到生成树的最短距离
  • 从任意起点(如0号顶点)开始,更新其邻接点的距离
  • 每次从未访问顶点中选出dist最小的顶点u,将其加入生成树
  • 用u更新其所有邻接点的距离
  • 重复上述过程直到所有顶点都被访问

代码实现(邻接矩阵):

#include <iostream>
#include <vector>
#include <climits>
using namespace std;
<p>const int INF = INT_MAX;</p><p>int prim(vector<vector<int>>& graph, int n) {
vector<int> dist(n, INF);
vector<bool> visited(n, false);
dist[0] = 0;
int totalWeight = 0;</p><pre class='brush:php;toolbar:false;'>for (int i = 0; i < n; i++) {
    int u = -1;
    for (int j = 0; j < n; j++) {
        if (!visited[j] && (u == -1 || dist[j] < dist[u]))
            u = j;
    }

    if (dist[u] == INF) return -1; // 图不连通
    visited[u] = true;
    totalWeight += dist[u];

    for (int v = 0; v < n; v++) {
        if (graph[u][v] != 0 && !visited[v] && graph[u][v] < dist[v]) {
            dist[v] = graph[u][v];
        }
    }
}
return totalWeight;

}

Kruskal算法:按边排序贪心选取

Kruskal算法基于贪心策略,将所有边按权值从小到大排序,依次尝试加入生成树,若加入后不形成环,则保留该边,否则跳过。

适用场景:稀疏图(边较少),使用边列表存储效率更高。

Kruskal算法关键点:

CA.LA CA.LA

第一款时尚产品在线设计平台,服装设计系统

CA.LA 94 查看详情 CA.LA
  • 需要对边进行排序
  • 使用并查集(Union-Find)判断是否形成环
  • 当加入n-1条边时,生成树完成

代码实现:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
<p>struct Edge {
int u, v, weight;
bool operator<(const Edge& other) const {
return weight < other.weight;
}
};</p><p>class UnionFind {
vector<int> parent;
public:
UnionFind(int n) {
parent.resize(n);
for (int i = 0; i < n; i++) parent[i] = i;
}</p><pre class='brush:php;toolbar:false;'>int find(int x) {
    if (parent[x] != x)
        parent[x] = find(parent[x]);
    return parent[x];
}

void unite(int x, int y) {
    parent[find(x)] = find(y);
}

bool connected(int x, int y) {
    return find(x) == find(y);
}

};

int kruskal(vector& edges, int n) { sort(edges.begin(), edges.end()); UnionFind uf(n); int totalWeight = 0; int edgesAdded = 0;

for (const Edge& e : edges) {
    if (!uf.connected(e.u, e.v)) {
        uf.unite(e.u, e.v);
        totalWeight += e.weight;
        edgesAdded++;
        if (edgesAdded == n - 1) break;
    }
}
return edgesAdded == n - 1 ? totalWeight : -1; // 不连通返回-1

}

两种算法对比与选择建议

理解两者差异有助于在实际问题中做出合适选择。

时间复杂度比较:

  • Prim(邻接矩阵):O(V²),适合顶点少、边多的情况
  • Prim(优先队列优化):O(E log V),适用于稀疏图
  • Kruskal:O(E log E),主要开销在排序,适合边较少的图

空间复杂度:

  • Prim通常使用邻接矩阵或邻接表,空间O(V²)或O(E)
  • Kruskal只需存储边列表,空间O(E)

选择建议:

  • 图很稠密(比如完全图)→ 优先考虑Prim
  • 图较稀疏或边已以列表形式给出 → Kruskal更直观高效
  • 需要频繁添加/删除边 → Kruskal更容易维护

基本上就这些。两种算法都能正确求出最小生成树,关键是根据数据规模和结构选择合适的方法。实际编程中注意处理图不连通的情况,避免无限循环或错误结果。

以上就是C++如何实现一个最小生成树算法_C++图论之Prim与Kruskal算法详解的详细内容,更多请关注其它相关文章!


# 管理机制  # 食品网站推广便宜  # 郑州seo效果评估  # seo优化pc端  # seo岗位所需技能  # 万江抖音seo流程  # 重庆360推广营销案例  # 40岁还能学seo吗  # 长春seo逻辑查询  # 长安搜索矩阵seo  # 开发区网站优化团队建设  # 复用  # 多路  # go  # 何为  # 较少  # 求出  # 图论  # 都是  # 两种  # 如何实现  # stream  # ios  # c++  # edge 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: sublime如何只显示或隐藏特定类型文件_sublime侧边栏文件过滤  我的世界mc.js免费游戏直接能玩 我的世界mc.js小游戏免费秒玩入口  AO3官方镜像站点汇总 AO3同人作品网页版直达链接  Node.js CSV 数据处理:基于字段值条件过滤整条记录的策略  mc.js游戏直达 mc.js网页免下载版本秒进地址  厨房不锈钢水槽发黑生锈怎么处理_水槽用可乐+锡纸2分钟抛亮如新  优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题  c++ 命名空间怎么用 c++ namespace使用指南  狙击外星人小游戏开始_狙击外星人小游戏立即开始  Python实时数据流中的动态最值查找策略  漫蛙漫画官方主页入口 漫蛙MANWA网页直达访问链接  React/Next.js中实现列表项的动态选择与移动  Sublime怎么配置Nim语言环境_Sublime Nim代码高亮与补全  抖音创作助手登录入口_抖音创作辅助工具官网直达  Golang如何使用net/url解析URL_Golang URL解析与处理方法  天猫2025双十一0点秒杀攻略 天猫爆款抢购时间  文心一言怎样用插件调度API数据_文心一言用插件调度API数据【API调用】  SteamMachine定价或为699美元 大家想入手吗?  在Blazor WebAssembly应用中动态注入客户端特定指标代码的策略  mysql如何设置表访问权限_mysql表访问权限配置  12306选座怎么选到商务座_12306商务座选择与配置说明  《刺客信条4:黑旗》重制版新细节曝光:无缝加载 地图更细致!  抓大鹅无需下载版 抓大鹅秒玩版入口  LINUX怎么设置定时任务_LINUX crontab配置教程  J*aScript实现单选按钮与关联输入框的联动禁用教程  Go语言HTML解析:利用Goquery精准获取指定元素内容  NRF24L01数据传输深度解析:解决大载荷接收异常与分包策略  2025俄罗斯Yandex最新入口 官方网站地址及浏览器下载指南  MAC怎么安装Homebrew包管理器_MAC为开发者和高级用户安装命令行工具  夸克浏览器桌面版同步不了书签怎么处理 夸克浏览器跨设备同步异常解决方案  Spring Boot内嵌服务器与J*a EE全栈特性:选择与部署策略  MAC怎么让Dock栏只显示当前运行的应用_MAC终端命令实现极简Dock栏  初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解  Windows电脑怎么截图最方便_系统自带截图工具的5种神仙用法【技巧】  俄罗斯Yandex搜索引擎入口_Yandex官网免登录一键访问  Python类型检查:优化关联可选属性的Mypy推断策略  Django通过AJAX异步上传图片并保存至模型的完整指南  使用Python高效删除Word宏并转换DOCM为DOCX格式  Golang如何使用bytes.Split分割字节切片_Golang bytes切片分割方法  菜鸟取件码是什么怎么查 最全查询渠道汇总  文本文档写html代码怎么运行_文本文档html代码运行步骤【教程】  如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!  漫蛙2在线漫画入口 漫蛙正版漫画网页版直达  C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果  Pandas DataFrame:高效添加条件计算列  J*aScript中如何高效提取对象指定属性  蛙漫移动版在线看 蛙漫手机浏览器直达入口  深入理解J*a链表中的IPosition接口与使用  京东单号查询入口_京东快递订单追踪入口  优化LangChain文档加载与ChromaDB集成:解决多文档处理与分块问题 

搜索