算法与数据结构(六):最小生成树(C++实现)

mac2025-12-08  4

文章目录

算法与数据结构(六):最小生成树(C++实现)Kruskal.cpp参考:算法分析与设计(C++描述) 石志国、刘冀伟、姚亦飞编著

算法与数据结构(六):最小生成树(C++实现)

对图进行深度优先搜素或者广度优先搜索,可以生成一颗深度优先搜索树或者广度优先搜索树。搜索的出发点不同,生成树的形态也不同。

在一个有权连通图中,生成树的各边权值之和最小的那棵树称作最小权值生成树,简称最小生成树。

Kruskal算法是一种按照网络中各边权值递增顺序构造最小生成树的方法。

Kruskal.cpp

//最小生成树的贪心算法Kruskal实现 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; struct Edge { int u, v, w;//u,v两个顶点.w:权值 Edge(){} Edge(int u0, int v0, int w0) :u(u0), v(v0), w(w0){} }; int n;//n:顶点个数 vector<Edge> edges;//edges:图g的所有边 int sum;//sum:最小生成树长 vector<Edge> mst;//mst:最小生成树,用边集表示 class DisjSets { vector<int> s; public: DisjSets(int n) :s(n, -1){}; int find(int x)//寻找点集根节点 { if (s[x] < 0) return x; else return s[x] = find(s[x]);//压缩路径 }; void UnionSets(int root1, int root2) { if (s[root1] > s[root2]) { s[root2] += s[root1]; s[root1] = root2; } else { s[root1] += s[root2]; s[root2] = s[root1]; } }; }; bool Cmp(const Edge &lhs, const Edge &rhs) { return lhs.w > rhs.w; } bool Kruskal() { DisjSets ds(n); make_heap(edges.begin(), edges.end(), Cmp);//对边集建堆,从小到大排序 int root1, root2; Edge e; while (!edges.empty()) { //从边中选取权值最小得边e e = edges.front(); /* pop_heap():Swaps the value in the position first and the value in the position last-1 * and makes the subrange [first, last-1) into a max heap */ pop_heap(edges.begin(), edges.end(), Cmp); edges.pop_back();//pop_back():Removes the last element of the container. root1 = ds.find(e.u), root2 = ds.find(e.v);//获取u,v所在的点集 if (root1 != root2) { sum += e.w;//调整最小生成树长度 mst.push_back(e);//边e放入最小生成树mst中去 ds.UnionSets(root1, root2); } if (mst.size() == n - 1) return true; } return false; } int main() { n = 6; edges.clear(); edges.push_back(Edge(0, 1, 6)); edges.push_back(Edge(0, 2, 15)); edges.push_back(Edge(0, 3, 10)); edges.push_back(Edge(1, 3, 11)); edges.push_back(Edge(1, 4, 8)); edges.push_back(Edge(2, 3, 5)); edges.push_back(Edge(2, 5, 9)); edges.push_back(Edge(3, 4, 4)); edges.push_back(Edge(3, 5, 8)); edges.push_back(Edge(4, 5, 12)); sum = 0; mst.clear(); if (Kruskal()) { cout << sum << endl; for (vector<Edge>::iterator it = mst.begin(); it != mst.end(); ++it) { cout << it->u << "->" << it->v << endl; } } else { cout << "有顶点不能到达!" << endl; } return 0; }

程序运行结果如下图所示:

参考:算法分析与设计(C++描述) 石志国、刘冀伟、姚亦飞编著

最新回复(0)