Kruskal算法

来源:互联网 发布:淘宝新3c怎么认证 编辑:程序博客网 时间:2024/04/29 20:29

上一篇博客实现了最小生成树的prim算法,prim算法中包含一个二重循环,算法复杂度为O(V^2),算法复杂度只和图中的节点个数V有关系,与图的稠密度无关,因此对于边很少的稀疏图来说,采用prim算法的效率很低,此时可以采用算法复杂度和边数相关的另一种最小生成树算法,Kruskal算法。

Kruskal算法的执行步骤可以描述为:

1.对图的所有边按照权值进行排序,初始阶段,每个节点自身构成一个连通分量

2.从小到大依次考察每条边的两端节点begin,end是否要加入当前的生成树集中,若begin和end位于同一个连通分量中,那么加入生成树集后会引入环,因此不进行加入操作

若begin,end不处于同一连通分量中,那么加入生成树集当中

3.循环执行第二步,直到所有的边都处理完


连通分量可以采用并查集实现,这里给出上述步骤的C++实现,求出下面给出的图的最小生成树。


C++代码:

// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<iostream>#include<vector>#include<algorithm>using namespace std;const int MAX = 7;int kset[MAX];struct Edge//定义edge结构体,{int begin;int end;int weight;Edge(int b, int e, int w) :begin(b), end(e), weight(w){}bool operator <(const Edge& e){return weight < e.weight;}};int find(int *kset,int x){if (x != kset[x])return kset[x] = find(kset,kset[x]);//并查集路径压缩,节省下次查找时间return x;}void kruskal(vector<Edge> &ve){for (int i = 0; i < MAX; i++)//初始化并查集kset[i] = i;sort(ve.begin(), ve.end());vector<Edge> result;for (vector<Edge>::iterator iter = ve.begin(); iter != ve.end(); iter++){int rb = find(kset,iter->begin);int re = find(kset, iter->end);if (rb!=re)//判断边的端点是否位于同一个连通分量中,边的两端点不处于同一连通分量中当中,将边加入最小生成树中{kset[rb] = re;result.push_back(*iter);}}//输出算法结果cout << "edge" << "   weight" << endl;for (vector<Edge>::iterator iter = result.begin(); iter != result.end(); iter++){cout << iter->begin << "--" << iter->end << "  " << iter->weight << endl;}}void test(){vector<Edge> ve;//构造图ve.push_back(Edge(0,1,12));ve.push_back(Edge(0,6,14));ve.push_back(Edge(0,5,16));ve.push_back(Edge(1,5,7));ve.push_back(Edge(1,2,10)); ve.push_back(Edge(2,5,6));ve.push_back(Edge(2,4,5));ve.push_back(Edge(2,3,3));ve.push_back(Edge(3,4,4));ve.push_back(Edge(4,5,2));ve.push_back(Edge(4,6,8));ve.push_back(Edge(5,6,9));kruskal(ve);}int _tmain(int argc, _TCHAR* argv[]){test();return 0;}

运行结果:



0 0
原创粉丝点击