克鲁斯卡尔(Kruskal )算法——求最小生成树贪心算法

克鲁斯卡尔算法是一种贪心算法,用于寻找加权图的最小生成树。它按照边的权重从小到大选择边,确保在不形成环的情况下连接所有顶点。算法包括边的排序、并查集的操作等步骤,广泛应用于网络布线、铁路规划和图像分割等领域。其时间复杂度为O(ElogE + ElogV),空间复杂度为O(V + E)。

克鲁斯卡尔算法是一种用于求解最小生成树问题的贪心算法。最小生成树是一个连通图的生成树,其边的权重之和最小。


一、原理

克鲁斯卡尔算法的核心思想是按照边的权重从小到大逐渐选择连通图的边,直到所有顶点都被连接为止。在每一步中,选择当前权重最小的边,若该边的两个顶点尚未连接,则将其添加到最小生成树的边集合中,并将这两个顶点归为同一个连通分量。通过不断地选择权重最小的边,保证了最小生成树的边权重之和最小。

二、步骤

下面是克鲁斯卡尔算法的具体步骤:

  1. 创建一个空的最小生成树的边集合。
  2. 将图中的所有边按权重从小到大进行排序。
  3. 遍历排序后的边集合,依次选择权重最小的边。
  4. 若该边的两个顶点尚未在最小生成树的边集合中相连(即添加该边不会形成环),则将该边添加到最小生成树的边集合中,并将这两个顶点归为同一个连通分量。
  5. 重复步骤3和步骤4,直到最小生成树的边数等于顶点数减1或者遍历完所有边。

假设遍历到一条由顶点 A 和 B 构成的边,而顶点 A 和顶点 B 标记不同,此时不仅需要将顶点 A 的标记更新为顶点 B 的标记,还需要更改所有和顶点 A 标记相同的顶点的标记,全部改为顶点 B 的标记。

克鲁斯卡尔(Kruskal )算法——求最小生成树贪心算法_算法

图 1

连通网例如,使用克鲁斯卡尔算法找图 1 的最小生成树的过程为:

首先,在初始状态下,对各顶点赋予不同的标记(用颜色区别),如下图所示:

克鲁斯卡尔(Kruskal's Algorithm)是一种用于寻找无向图中最小生成树贪心算法。在C++中编写这个算法,你需要以下几个步骤: 1. **创建数据结构**: - 使用`std::vector<std::pair<int, std::pair<int, int>>> edges;`存储边的信息,其中每个元素是一个三元组`(weight, u, v)`,代表从节点u到节点v的边及其权重。 2. **按权重排序**: - 首先对所有边按照权重从小到大排序。 ```cpp bool compareEdges(const std::pair<int, std::pair<int, int>>& a, const std::pair<int, std::pair<int, int>>& b) { return a.first < b.first; } std::sort(edges.begin(), edges.end(), compareEdges); ``` 3. **构建最小生成树**: - 初始化一个集合(通常使用邻接表表示),用来记录哪些边已经被添加到最小生成树中。 - 循环遍历排序后的边,每次选择一条未加入的边,并检查这条边连接的两个顶点是否在一个连通分量内(即它们还未被包含在其他边的集合中)。 - 如果可以合并,就将这条边加入到最小生成树,并更新连通分量信息。 ```cpp int n = vertices.size(); std::set<std::pair<int, int>> mstSet; while (edges.size() && mstSet.size() != n - 1) { int minEdge = INT_MAX; int u = -1, v = -1; for (const auto& edge : edges) { if (mstSet.find(edge.second.first) == mstSet.end() && mstSet.find(edge.second.second) == mstSet.end() && edge.first < minEdge) { minEdge = edge.first; u = edge.second.first; v = edge.second.second; } } if (u != -1 && v != -1) { edges.erase(std::remove(edges.begin(), edges.end(), {minEdge, {u, v}}), edges.end()); mstSet.insert({u, v}); } } ``` 4. **返回最小生成树**: 最终,`mstSet`包含了最小生成树的所有边。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值