邻接矩阵实现克鲁斯卡尔算法

本文介绍了一个使用克鲁斯卡尔算法求解无向图最小生成树的C语言程序实例。该程序首先创建了一个包含顶点和边的无向图,并通过邻接矩阵表示它们之间的连接关系。接着,利用克鲁斯卡尔算法找出图中权值最小的生成树,并输出生成树的具体组成及其总权值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//主要源代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 999999
#define MAX_NAME 3
#define VERTEX_MAX_NUM 100
typedef char VertexType[MAX_NAME];
typedef int VRType;
typedef struct {    //建立邻接矩阵
    int weight;
}adjMatrix[VERTEX_MAX_NUM][VERTEX_MAX_NUM];
struct MGraph{
    VertexType vex[VERTEX_MAX_NUM];//建立顶点向量
    adjMatrix arcs;  //图中的邻接矩阵
    int vrtnum,arcnum;//顶点,弧的个数
};
typedef struct Sort{
    int x,y,w;
}weightValue[VERTEX_MAX_NUM*VERTEX_MAX_NUM];
typedef struct VRTFather{
    int fa;
}Father[VERTEX_MAX_NUM];
int LocateVex(MGraph G,VertexType u){
    int i;
    for( i=0;i<G.vrtnum;i++)
        if(strcmp(u,G.vex[i])==0)
         return i;
    return -1;
}
void creatMGraph(MGraph &G){
    int i,j,w;
    VertexType va,vb;
    printf("请输入无向图G的顶点数、边数:");
    scanf("%d %d",&G.vrtnum,&G.arcnum);
    printf("请输入%d个顶点的值:\n",G.vrtnum);
    for(i=0;i<G.vrtnum;i++) //构造顶点向量,(其实就是将顶点的名字换成数字)
        scanf("%s",G.vex[i]);
    for(i=0;i<G.vrtnum;i++) //初始化邻接矩阵,都赋为无穷
        for(j=0;j<G.vrtnum;j++)
            G.arcs[i][j].weight=INF;
    printf("请输入%d条边的顶点1 顶点2 权值(以空格为间隔):\n",G.vrtnum);
    for(int k=0;k<G.arcnum;k++){
        scanf("%s%s%d%*c",va,vb,&w);
        i=LocateVex(G,va);
        j=LocateVex(G,vb);
        G.arcs[i][j].weight=G.arcs[j][i].weight=w;
    }
}
void DisplayArc(MGraph g){
    printf("建立的邻接矩阵如下:\n  ");
    for(int i=0;i<g.vrtnum;i++)
        printf("%7s",g.vex[i]);
    printf("\n");
    for(int i=0;i<g.vrtnum;i++){
         printf("%s",g.vex[i]);
        for(int j=0;j<g.vrtnum;j++){
            if(g.arcs[i][j].weight==INF)
                printf("     ∞");
            else
                printf("%7d",g.arcs[i][j].weight);
        }
        printf("\n");
    }
}
int findFather(int x,Father &father)
{
    int root;//找x顶点的父亲
    while(x!=father[x].fa)
    x=father[x].fa;
    root=x;//用temp存储x的最深根节点。即x的父亲结点
    return root;
}
void MiniSpanTree_KRUSKAL(MGraph G){
    int min=INF,i,j,vx,vy;
    weightValue value,temp;
    Father father;
    for(i=0;i<G.vrtnum;i++)//初始化所有顶点的父亲为他自己
        father[i].fa=i;
    int k=0;
    //将所有的边(包括边两端顶点信息),赋值到value结构体数组中
    for(i=0;i<G.vrtnum;i++)
    for(j=0;j<G.vrtnum;j++,k++){
        value[k].w=G.arcs[i][j].weight;
        value[k].x=i;value[k].y=j;
    }
    //对value数组中所有的边进行从大到小排序
    for(i=0; i<G.vrtnum*G.vrtnum-1; i++)
    for(j=0; j<G.vrtnum*G.vrtnum-1-i; j++){
       if(value[j].w>value[j+1].w){
            temp[0]=value[j+1];
            value[j+1]=value[j];
            value[j]=temp[0];
       }
    }
    printf("克鲁斯卡尔算法的最小生成树为:\n");
    int allcost=0;
    for(i=0;i<2*G.arcnum-1;i+=2){
        //从value数组中每隔两个点进行取边的值,因为无向图中每个顶点的值有两个
        int a,b;
        a=value[i].x;
        b=value[i].y;
        if(findFather(a,father)!=findFather(b,father)){
            //当前边和其他边不构成环,就输出这条边
            printf("(%s-%s) %d\n",G.vex[a],G.vex[b],G.arcs[a][b].weight);
            //将此边的右顶点的父亲赋值为左顶点的父亲
            father[father[b].fa].fa=findFather(a,father);
            allcost+=G.arcs[a][b].weight;//每输出一次,累加此边的权值
        }
    }
    printf("最小二叉树的最小权值为:%d\n",allcost);
}


int main(){


    MGraph g;
    creatMGraph(g);
    DisplayArc(g);
    MiniSpanTree_KRUSKAL(g);
    return 0;
}
/*
测试样例:
v0 v1 v2 v3 v4 v5 v6
v0 v1 28
v1 v2 16
v2 v3 12
v3 v4 22
v4 v5 25
v5 v0 10
v1 v6 14
v3 v6 18
v4 v6 24
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值