经典算法之Kruskal算法

来源:互联网 发布:unix环境高级编程答案 编辑:程序博客网 时间:2024/06/06 16:47
/************************author's email:wardseptember@gmail.comdate:2017.12.13************************//*每次找出候选边中权值最小的边,就将该边并入生成树中。重复此过程直到所有边都被检测完。Kruskal算法的关键在于找出最小边和判断此最小边并入树是否形成回路。*/#include<iostream>#define INF 100//INF为比图中任何权值都大的数#define maxSize 6   //图的顶点数#define number 10   //图的边数using namespace std;typedef struct {//图的定义    float edges[maxSize][maxSize];//邻接矩阵的定义    int n, e;   //分别为顶点数和边数}MGraph;MGraph createGraph(MGraph g);typedef struct {    int a, b;   //a和b为一条边所连的两个顶点    int weight; //边的权值}Road;int v[maxSize];  //定义并查集数组void createRoad(Road *road);//依照图构造各边int getRoot(int a);        //在并查集中查找根的结点void bubbleSort(Road *road,int E); //依照各边的权值对各边进行冒泡排序,升序void Kruskal(MGraph g, int &sum, Road *road);//Kruskal算法int main() {    Road road[number];//存放各边    /*初始化各边*/    for (int i = 0; i < 10; ++i) {        road[i].weight = 0;        road[i].a = 0;        road[i].b = 0;    }    int sum ;//权值    MGraph g;//定义并初始化图g    g.edges[maxSize][maxSize] = { 0 };    g.n = maxSize; g.e = 10;    g = createGraph(g);//创建一个图    createRoad(road);//依照图构造各边    Kruskal(g, sum, road);//Kruskal算法    cout << "最小生成树的权值为:";    cout << sum << endl;    return 0;}MGraph createGraph(MGraph g) {//此图的各个顶点为一个正无边形的顶点,加正中间一个点。正中间一个点与各个顶点相连    int i, j;    for (i = 0; i < maxSize; i++)    {        for (j = 0; j < maxSize; j++)        {            g.edges[i][j] = INF;        }    }    g.edges[0][1] = 6;    g.edges[1][0] = 6;    g.edges[0][2] = 1;    g.edges[2][0] = 1;    g.edges[0][3] = 5;    g.edges[3][0] = 5;    g.edges[1][2] = 4;    g.edges[2][1] = 4;    g.edges[1][4] = 3;    g.edges[4][1] = 3;    g.edges[2][3] = 2;    g.edges[3][2] = 2;    g.edges[2][4] = 7;    g.edges[4][2] = 7;    g.edges[2][5] = 8;    g.edges[5][2] = 8;    g.edges[3][5] = 9;    g.edges[5][3] = 9;    g.edges[4][5] = 11;    g.edges[5][4] = 11;    g.n = maxSize;    g.e = 10;    return g;}void createRoad(Road *road) {//依照图构造各边    road[0].a = 0;    //顶点0    road[0].b = 1;    //顶点1    road[0].weight = 6;//顶点0和顶点1之间的权值    road[1].a = 0;    road[1].b = 2;    road[1].weight = 1;    road[2].a = 0;    road[2].b = 3;    road[2].weight = 5;    road[3].a = 3;    road[3].b = 2;    road[3].weight = 2;    road[4].a = 2;    road[4].b = 1;    road[4].weight = 4;    road[5].a = 2;    road[5].b = 5;    road[5].weight = 8;    road[6].a = 2;    road[6].b = 4;    road[6].weight = 7;    road[7].a = 1;    road[7].b = 4;    road[7].weight = 3;    road[8].a = 3;    road[8].b = 5;    road[8].weight = 9;    road[9].a = 5;    road[9].b = 4;    road[9].weight = 11;}int getRoot(int a) {   //在并查集中查找根的结点    while (a != v[a])        a = v[a];    return a;}void bubbleSort(Road *road, int E) {//依照各边的权值对各边进行冒泡排序,升序    int i, j, temp1,temp2,temp3, flag;/*temp1、temp2、temp3用于交换,flag用来标记是    否发生的了交换,没发生交换代表road已全部有序*/    /*冒泡排序*/    for (i = E - 1; i >= 1; --i) {        flag = 0;        for (j = 1; j <= i; ++j) {            if (road[j - 1].weight > road[j].weight) {                temp1 = road[j].weight;                temp2 = road[j].a;                temp3 = road[j].b;                road[j].weight = road[j - 1].weight;                road[j].a = road[j - 1].a;                road[j].b = road[j - 1].b;                road[j - 1].weight = temp1;                road[j - 1].a = temp2;                road[j - 1].b = temp3;                flag = 1;            }        }        if (flag == 0)            break;    }}void Kruskal(MGraph g, int &sum, Road *road) {//Kruskal算法    int i;    int N, E, a, b;    N = g.n;//图的顶点数    E = g.e;//图的边数    sum = 0;    for (i = 0; i < N; ++i)        v[i] = i;    bubbleSort(road, E);//对road数组的E条边按其权值大小从小到大排序    /*下面这个循环求最小生成树的权值*/    for (i = 0; i < E; ++i) {        a = getRoot(road[i].a);        b = getRoot(road[i].b);        if (a != b) {//没有形成回路,才并入最小生成树            v[a] = b;            sum += road[i].weight;//求最小生成树的权值。这里可以进行输出或者其他操作        }    }}

以上如有错误,请指出,大家共同学习进步。

原创粉丝点击