您的位置:首页 > 编程语言 > C语言/C++

Kruskal算法求最小生成树的c++代码实现

2017-09-29 15:52 781 查看
kruskal算法是一类适用于稀疏图的最小生成树算法,主要思想也很简单,将所有的边分为 属于生成树的边S和不属于的V-S ,每次在V-S中找一个权值最小的边放入S中,同时该边不构成回路,关于是否构成回路,可以使用并查集来判断。比如



上图中假如{1,2} , {1,3}都已经属于,那么unionSet[3]  = unionSet[2] = unionSet[1] = 1;这时如果想加入{1,3},此时unionSet[2] == unionSet[1] 则会构成回路。

循环的终止条件是放入S中的边的个数等于 顶点个数-1.

#include <iostream>
#include<vector>
#include<queue>
using namespace std;

struct Edge{
int startP;
int endP;
int weight;
Edge(int s, int e, int w):startP(s), endP(e), weight(w){};
};

struct cmp{
bool operator() (Edge e1, Edge e2) const{
return e1.weight >= e2.weight;
}
};

int find(const vector<int>& unionSet, int index) //通过并查集找到index所属的类别
{
while( unionSet[index] != index){
index = unionSet[index];
}
return index;
}

vector<Edge>  Kruskal(  priority_queue<Edge, vector<Edge>, cmp> edges, vector<int> unionSet){
int num_points = unionSet.size();
vector<Edge> MST;
while( MST.size() < num_points -1){ //当MST的size 等于点的个数-1的时候完成生成最小生成树
if(  find(unionSet, edges.top().startP) != find(unionSet, edges.top().endP)  ) //如果起点终点属于同一类,则构成回路
{
MST.push_back(edges.top());
unionSet[ find(unionSet, edges.top().endP )] = find(unionSet, edges.top().startP );
}
edges.pop();
}
return MST;
}
void show(const vector<Edge>& MST){ //显示函数
for(int i = 0; i < MST.size(); i++)
cout << MST[i].startP+1 << "->" << MST[i].endP+1 << endl;
}

int main()
{

Edge Edge_array[10] = {Edge(0,1,6), Edge(0,2,1), Edge(0,3,5), Edge(1,2,5), Edge(1,4,3), Edge(2,3,5),Edge(2,4,6), Edge(2,5,4), Edge(3,5,2), Edge(4,5,6)};
priority_queue<Edge, vector<Edge>, cmp> Edgs_pq;
for(int i = 0; i < 10; i++)
Edgs_pq.push(Edge_array[i]); //初始化优先队列,将各个边按照权值从小到大放入优先队列中
vector<int> unionSet( 6 , -1 );
for(int i = 0; i < 6; i++)
unionSet[i] = i; //初始化并查集

vector<Edge> MST = Kruskal(Edgs_pq, unionSet);
show(MST);

return 0;
}
结果按照先后顺序依次输出放入的边,如下:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: