图的最小生成树——Kruskal算法

Kruskal算法的基本思想用伪代码描述如下:

1. 初始化:U=V;TE={ }; 
2. 重复下述操作直到T中的连通分量个数为1:
    2.1 在E中寻找最短边(u,v);
    2.2 如果顶点u、v位于T的两个不同连通分量,则
          2.2.1 将边(u,v)并入TE;
          2.2.2 将这两个连通分量合为一个;
    2.3 标记边(u,v),使得(u,v)不参加后续最短边的选取;

源码:

#include<iostream>
#include<vector>
#include<queue>
#include<iomanip>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define VertexData unsigned int//顶点序号类型
#define vexCounts 6
char vextex[]= { 'A', 'B', 'C', 'D', 'E', 'F' };
unsigned int adjMat[vexCounts][vexCounts];

typedef struct
{
    VertexData u;
    VertexData v;
    unsigned int cost;
}Arc;
void GetAdjMat(unsigned int adjMat[][vexCounts])
{
    for(int i=0;i<vexCounts;i++)
         for(int j=0;j<vexCounts;j++)
    {
        if(i==j)    adjMat[i][j]=0;
        else adjMat[i][j]=INF;
    }
    adjMat[0][1] = 6; adjMat[0][2] = 1; adjMat[0][3] = 5;
    adjMat[1][0] = 6; adjMat[1][2] = 5; adjMat[1][4] = 3;
    adjMat[2][0] = 1; adjMat[2][1] = 5; adjMat[2][3] = 5; adjMat[2][4] = 6; adjMat[2][5] = 4;
    adjMat[3][0] = 5; adjMat[3][2] = 5; adjMat[3][5] = 2;
    adjMat[4][1] = 3; adjMat[4][2] = 6; adjMat[4][5] = 6;
    adjMat[5][2] = 4; adjMat[5][3] = 2; adjMat[5][4] = 6;


}

void ReadArc(unsigned int adjMat[][vexCounts],vector<Arc> &vertexArc)//读取边信息
{
    Arc* temp=NULL;
    for(unsigned int i=0;i<vexCounts;i++)
    {
        for(unsigned int j=0;j<i;j++)
        {
            if(adjMat[i][j]!=INF&&adjMat[i][j]!=0)
            {
                temp=new Arc;
                temp->u=i;
                temp->v=j;
                temp->cost=adjMat[i][j];
                vertexArc.push_back(*temp);
            }
        }
    }
}

bool compare(Arc A,Arc B)
{
    return A.cost<B.cost?true:false;
}

bool FindTree(VertexData u,VertexData v,vector<vector<VertexData> >&Tree)//查找可添加树
{
    int index_u=INF;
    int index_v=INF;
    for(int i=0;i<Tree.size();i++)//检查u,v分别属于哪棵树
    {
        if(find(Tree[i].begin(),Tree[i].end(),u)!=Tree[i].end())
            index_u=i;
        if(find(Tree[i].begin(),Tree[i].end(),v)!=Tree[i].end())
            index_v=i;
    }
    if(index_u!=index_v)//u,v不在一棵树,合并两棵树
    {
        for(int i=0;i<Tree[index_v].size();i++)
        {
            Tree[index_u].push_back(Tree[index_v][i]);
        }
        Tree[index_v].clear();
        return true;
    }
    return false;
}

void MiniSpanTree_Kruskal(unsigned int adjMat[][vexCounts])//Kruskal算法
{
    vector<Arc> vertexArc;
    ReadArc(adjMat,vertexArc);//读取边信息
    sort(vertexArc.begin(),vertexArc.end(),compare);//边从小到大排序
    vector<vector<VertexData> >Tree(vexCounts);//6棵独立树
    for(int i=0;i<vexCounts;i++)
    {
        Tree[i].push_back(i);//初始化6棵独立树的信息
    }
    for(int i=0;i<vertexArc.size();i++)//从小到大取最小代价边
    {
        VertexData u=vertexArc[i].u;
        VertexData v=vertexArc[i].v;
        if(FindTree(u,v,Tree))//检查此边的顶点是否在一棵树
        {
            cout<<vextex[u]<<"---"<<vextex[v]<<endl;//把此边加入到最小生成树中
        }
    }
}

int main()
{
    adjMat[vexCounts][vexCounts]={0};
    GetAdjMat(adjMat);
    cout<<"打印顶点:"<<endl;
    for(int i=0;i<vexCounts;i++) cout<<vextex[i]<<" ";
    cout<<endl<<"打印邻接矩阵:"<<endl;
    for(int i=0;i<vexCounts;i++)
         for(int j=0;j<vexCounts;j++)
    {
        if(adjMat[i][j]==INF)    cout<<setw(5)<<"INF";
        else cout<<setw(5)<<adjMat[i][j];
        if(j==vexCounts-1) cout<<endl;
    }
    cout<<endl<<"--------------Kruskal---------------"<<endl;
    MiniSpanTree_Kruskal(adjMat);
    return 0;
}

截图:




猜你喜欢

转载自blog.csdn.net/arthu6/article/details/80809120
今日推荐