Kruskal算法构造最小生成树

Kruskal算法来构造最小生成树,我总结了分为以下步骤:

(1)建图,构造Kruskal边集,边集元素应该包括该边的起始顶点、终止顶点、权值;

(2)将边集按权值从小到大的顺序进行排序;

(3)从小到大依次从Kruskal边集中取边加入最小生成树集合,判断条件:将该边加入最小生成树集合,与生成树集合中原有的边构成

(4)最小生成树集合中元素(构成生成树的边)的个数为原图顶点数-1时,代表最小生成树构造完毕。

Kruskal核心伪代码如下:

Kruskal(MGragh *Gra)
{
    对Kruskal边集按权值从小到大排序

    for (边集)
    {
        // 判断边集中的边能否加入最小生成树集合

        n=该边的起始顶点所能到达的最新顶点
        m=该边的终止顶点所能到达的最新顶点

        如果n等于m 说明该边能够成环路,所以不能加入最小生成树集合

        如果n不等于m 说明该边可以加入最小生成树集合
        {
            更新:n能够到达m
        }
    }
}

实例:

源代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #define MAX_VERTEX_NUM 100
  6 #define MAX_EDGE_NUM 200
  7 #define MAX_VERTEX_NAMELEN 100
  8 
  9 typedef struct{
 10     char name[MAX_VERTEX_NAMELEN];
 11 }VerType;
 12 
 13 // 图的邻接矩阵存储结构
 14 typedef struct{
 15     int VertexNum,EdgeNum;                        // 顶点数,边数
 16     VerType Vertex[MAX_VERTEX_NUM];               // 顶点集
 17     int Edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM];     // 边集
 18 }MGragh;
 19 
 20 // 克鲁斯卡尔边集
 21 typedef struct{
 22     int b;        // 起始顶点
 23     int e;        // 终结顶点
 24     int w;        // 权值
 25 }KruskalEdge;
 26 KruskalEdge edge[MAX_EDGE_NUM];
 27 
 28 // 快速排序cmp
 29 int cmp(const void *a, const void *b)
 30 {
 31     KruskalEdge *c = (KruskalEdge *)a;
 32     KruskalEdge *d = (KruskalEdge *)b;
 33 
 34     // 权值从小到大排序 权值相同则按起始顶点从小到大排序
 35     if (c->w != d->w){
 36         return c->w - d->w;
 37     }
 38     else{
 39         return c->b - d->b;
 40     }
 41 }
 42 
 43 // 邻接矩阵建图及建立克鲁斯卡尔边集
 44 void CreateMGragh(MGragh *Gra)
 45 {
 46     int i,j,k,w;
 47     char v1[MAX_VERTEX_NAMELEN],v2[MAX_VERTEX_NAMELEN];
 48     
 49     printf("请输入顶点数及边数(顶点数 边数)\n");
 50     scanf("%d %d%*c",&(Gra->VertexNum),&(Gra->EdgeNum));
 51     
 52     printf("请输入顶点信息\n");
 53     for (i=0; i<Gra->VertexNum; i++){
 54         printf("%d.",i+1);
 55         gets(Gra->Vertex[i].name);
 56     }
 57     
 58     // 初始化邻接矩阵
 59     for (i=0; i<Gra->VertexNum; i++){
 60         for (j=0; j<Gra->VertexNum; j++){
 61             Gra->Edge[i][j] = 0;
 62         }
 63     }
 64     printf("请输入边信息(顶点,顶点,权值)\n");
 65     for (i=0; i<Gra->EdgeNum; i++){
 66         printf("%d.",i+1);
 67         scanf("%[^,]%*c%[^,]%*c%d%*c",v1,v2,&w);
 68 
 69         for (j=0; j<Gra->VertexNum; j++){
 70             for (k=0; k<Gra->VertexNum; k++){
 71                 if (strcmp(Gra->Vertex[j].name,v1) == 0 && strcmp(Gra->Vertex[k].name,v2) == 0){
 72                     Gra->Edge[j][k] = Gra->Edge[k][j] = w;
 73 
 74                     // 构造克鲁斯卡尔边集 使起始顶点<终止顶点
 75                     if (j<k){
 76                         edge[i].b = j;
 77                         edge[i].e = k;
 78                         edge[i].w = w;
 79                     }
 80                     else{
 81                         edge[i].b = k;
 82                         edge[i].e = j;
 83                         edge[i].w = w;
 84                     }
 85                 }
 86             }
 87         }
 88     }
 89 
 90     // 将克鲁斯卡尔边集按权值从小到大排序
 91     qsort(edge,Gra->EdgeNum,sizeof(edge[0]),cmp);
 92 }
 93 
 94 // 找到顶点t所能到达的在时间顺序上最新的点 
 95 // 例如p[0]=6 代表第0个点能够到达第6个点
 96 int FindLastArrived(int *p, int t)
 97 {
 98     while (p[t] > 0){
 99         t = p[t];
100     }
101     return t;
102 }
103 
104 // 克鲁斯卡尔算法构造最小生成树
105 void MiniTreeByKruskal(MGragh *Gra)
106 {
107     int i,n,m;
108     int p[MAX_VERTEX_NUM];
109 
110     // 初始化辅助数组
111     for (i=0; i<Gra->VertexNum; i++){
112         p[i] = 0;
113     }
114 
115     printf("\nKruskal算法构造最小生成树为:\n");
116     for (i=0; i<Gra->EdgeNum; i++){
117         n = FindLastArrived(p,edge[i].b);
118         m = FindLastArrived(p,edge[i].e);
119         if (n != m){    // 如果n==m 说明存在环路
120             p[n] = m;    // 将边加入生成树,并令n能到达m
121             printf("(%s --> %s) %d\n",Gra->Vertex[edge[i].b].name,Gra->Vertex[edge[i].e].name,edge[i].w);
122         }
123     }
124 }
125 
126 int main()
127 {
128     MGragh g;
129     CreateMGragh(&g);
130     MiniTreeByKruskal(&g);
131     return 0;
132 }

测试用例及结果:

posted on 2013-08-16 22:03  RAUL_AC  阅读(1619)  评论(0编辑  收藏  举报

导航