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

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

Kruskal算法求最小生成树的c++代码实现_第1张图片

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

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

#include 
#include
#include
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& unionSet, int index) //通过并查集找到index所属的类别
{
    while( unionSet[index] != index){
        index = unionSet[index];
    }
    return index;
}

vector  Kruskal(  priority_queue, cmp> edges, vector unionSet){
    int num_points = unionSet.size();
    vector 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& 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, cmp> Edgs_pq;
    for(int i = 0; i < 10; i++)
        Edgs_pq.push(Edge_array[i]); //初始化优先队列,将各个边按照权值从小到大放入优先队列中
    vector unionSet( 6 , -1 ); 
    for(int i = 0; i < 6; i++)
        unionSet[i] = i; //初始化并查集

    vector MST = Kruskal(Edgs_pq, unionSet);
    show(MST);



    return 0;
}
结果按照先后顺序依次输出放入的边,如下:
Kruskal算法求最小生成树的c++代码实现_第2张图片

你可能感兴趣的:(算法)