邻接矩阵+边集数组+克鲁斯卡尔

17 篇文章 0 订阅
17 篇文章 0 订阅

题目描述:

利用克鲁斯卡尔的方法生成最小树。

分析:

这个方法简单粗暴。
邻接矩阵讲解:https://blog.csdn.net/qq_43506138/article/details/86599865
简单的讲,就是将边集数组中的边依次打印就好,不过在打印的前提是所要即将打印的这条边不会和之前打印的边成为回路。
所以,这个方法只要在把边集数组转换出来后,在一个函数判断回路就可以了。

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
typedef char VertexType;
typedef int EdgeType;
#define MAXVEX 100
#define MAXEDGE 100
#define INFINITY 65535
typedef struct
{
    VertexType vexs[MAXVEX];
    EdgeType arc[MAXVEX][MAXVEX];
    int numEdge,numVexs;
}MGraph;
typedef struct
{
    int begin;
    int end;
    int weight;
}Edge;
void CreateMGraph(MGraph *G)
{
    int i,j,k,weight;
    printf("请输入顶点数和边数:\n");
    scanf("%d%d",&G->numVexs,&G->numEdge);
    for(i=0;i<G->numVexs;i++)   //初始化邻接矩阵
        for(j=0;j<G->numVexs;j++)
           {
               if(i==j)
                  G->arc[i][j]=0;
               else
                G->arc[i][j]=INFINITY;
           }
    for(k=0;k<G->numEdge;k++)
    {
        printf("请输入边的相关信息(包括权):\n");
        scanf("%d%d%d",&i,&j,&weight);
        G->arc[i][j]=weight;
        G->arc[j][i]=weight;
    }
}
//将邻接矩阵转化为边集数组
void TransEdge(Edge edge[],MGraph *G)
{
    int i,j,k=0;
    //依次将邻接矩阵中的有权的地方保存下来
    for(i=0;i<G->numEdge;i++)
        for(j=0;j<G->numEdge;j++)
            {
                if(G->arc[i][j]!=0&&G->arc[i][j]!=INFINITY)
                {
                    edge[k].begin=i;
                    edge[k].end=j;
                    edge[k].weight=G->arc[i][j];
                    k++;
                }
            }
  //按照权排序
    for(i=0;i<k-1;i++)
        for(j=i+1;j<k;j++)
            {
                if(edge[i].weight>edge[j].weight)
                {
                    Edge T;
                    T=edge[i];edge[i]=edge[j];edge[j]=T;
                }
            }
}
//查找连线顶点的尾部下标
int Find(int *parent,int f)
{
    while(parent[f]>0)
        f=parent[f];
    return f;
}
//最小生成树(克鲁斯卡尔)
void MiniSpanTree_Kruskal(MGraph G)
{
    int i,j,k;
    Edge edge[MAXEDGE];//边集数组
    int parent[MAXVEX];//判断边与边之间是否形成回路的用处
    for(i=0;i<MAXVEX;i++)//初始化parent
        parent[i]=0;
    TransEdge(edge,&G);//得到边集数组
    //循环每一条边
    for(i=0;i<G.numEdge;i++)
    {
        int n=Find(parent,edge[i].begin);
        int m=Find(parent,edge[i].end);
        if(n!=m)//成立则表示未成回路
        {//将此边的结尾顶点放入下标为起点的parent中
        //表示此顶点已经在生成树集合中
            parent[n]=m;
        //打印此边相关信息
            printf("(%d %d) :%d \n",edge[i].begin,edge[i].end,edge[i].weight);
        }
    }
}
int main()
{
    MGraph G;
    CreateMGraph(&G);
    printf("邻接矩阵已创建完成,开始生成最小树(克鲁斯卡尔):\n");
    MiniSpanTree_Kruskal(G);
}

本代码难点在于Find函数和parent数组的理解,多演示几次就能很好理解了。简单的讲,Find函数,就是查找这个顶点线路的最后一个顶点

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值