最小生成树-克鲁斯卡尔算法

一个人想着一个人 提交于 2019-11-30 10:26:05

最小生成树-克鲁斯卡尔算法

算法思想

1.将图的所有连接线去掉,只剩顶点

2.从图的边集数组中找到权值最小的边,将边的两个顶点连接起来

3.继续寻找权值最小的边,将两个顶点之间连接起来,如果选择的边使得最小生成树出现了环路,则放弃该边,选择权值次小的边

4.直到所有的顶点都被连接在一起并且没有环路,最小生成树就生成了。

 

克鲁斯卡尔算法代码

//在连通网中求出最小生成树

#include <stdio.h>

#include <stdlib.h>

 

#define MAXEDGE 20

#define MAXVEX  20

#define INFINITY 65535

 

typedef struct

{

    int arc[MAXVEX][MAXVEX];

    int numVertexes, numEdges;//顶点数,边数

}MGraph;

 

typedef struct

{

    int begin;

    int end;

    int weight;

}Edge;   //对边集数组Edge结构的定义

 

//创建图的邻接矩阵

void CreateMGraph(MGraph *G) {

    int i, j;

 

    G->numEdges=11;

    G->numVertexes=7;

 

    for (i = 0; i < G->numVertexes; i++) {

        for ( j = 0; j < G->numVertexes; j++) {

            if (i==j)

                G->arc[i][j]=0;

            else

                G->arc[i][j] = G->arc[j][i] = INFINITY;

        }

    }

    G->arc[0][1]=7;

    G->arc[0][3]=5;

    G->arc[1][2]=8;

    G->arc[1][3]=9;

    G->arc[1][4]=7;

    G->arc[2][4]=5;

    G->arc[3][4]=15;

    G->arc[3][5]=6;

    G->arc[4][5]=8;

    G->arc[4][6]=9;

    G->arc[5][6]=11;

 

    for(i = 0; i < G->numVertexes; i++) {

        for(j = i; j < G->numVertexes; j++) {

            G->arc[j][i] =G->arc[i][j];

        }

    }

 

}

 

//快速排序的条件

int cmp(const void* a, const void* b) {

    return (*(Edge*)a).weight - (*(Edge*)b).weight;

}

 

//找到根节点

int Find(int *parent, int f) {

    while ( parent[f] > 0) {

        f = parent[f];

    }

    return f;

}

 

// 生成最小生成树

void MiniSpanTree_Kruskal(MGraph G) {

    int i, j, n, m;

    int k = 0;

    int parent[MAXVEX]; //用于寻找根节点的数组

 

    Edge edges[MAXEDGE]; //定义边集数组,edge的结构为begin,end,weight,均为整型

 

    // 用来构建边集数组并排序(将邻接矩阵的对角线右边的部分存入边集数组中)

    for ( i = 0; i < G.numVertexes-1; i++) {

        for (j = i + 1; j < G.numVertexes; j++) {

            if (G.arc[i][j] < INFINITY) {

                edges[k].begin = i; //编号较小的结点为首

                edges[k].end = j;   //编号较大的结点为尾

                edges[k].weight = G.arc[i][j];

                k++;

            }

        }

    }

 

    //为边集数组Edge排序

    qsort(edges, G.numEdges, sizeof(Edge), cmp);

 

    for (i = 0; i < G.numVertexes; i++)

        parent[i] = 0;

 

    printf("打印最小生成树:\n");

    for (i = 0; i < G.numEdges; i++) {

        n = Find(parent, edges[i].begin);//寻找边edge[i]的“首节点”所在树的树根

        m = Find(parent, edges[i].end);//寻找边edge[i]的“尾节点”所在树的树根

 

        //假如n与m不等,说明两个顶点不在一棵树内,因此这条边的加入不会使已经选择的边集产生回路

        if (n != m) {

            parent[n] = m;

            printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);

        }

    }

}

 

int main(void)

{

    MGraph G;

    CreateMGraph(&G);

    MiniSpanTree_Kruskal(G);

 

    return 0;

}

原文链接:https://blog.csdn.net/junya_zhang/article/details/83584592

原文链接:https://blog.csdn.net/hhu1506010220/article/details/51971717

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!