数据结构_图的应用_最小生成树1(普里姆算法)

 

 

 

1、 先来说明什么叫最小生成树

最小生成树MST minimum spanning tree )的 性质如下

 

G=(VE)是一个带权连通图, V是顶点集,UV的一个非空子集,若(u0,v0)是一条最小权值的边,其中u0ÎUv0ÎV-U(u0,v0)必在最小生成树上。 

 

2、引入实际问题

有8个村落(V0 -- V7)分布在各个地区,政府打算用最少的资金来把这8个村落连起来,可以使得不管在哪个村子都可以到其他7个村子,已知可以两两之间可以互通的村子以及其建好其之间的路段需要花费的金钱,如图所示(备注:两两之前的数值以千元为单位):

3、代码实现

首先构建其邻接矩阵,来存储图:

 

 

其生成代码参考如下:

#include<stdio.h>
#define MNUM 10
typedef struct
{
    int vexs[MNUM];  //这里把数字作为顶点的代表  如果是字母可以为char vexs[MNUM];
    int arcs[MNUM][MNUM];
    int vexnum, arcnum;
}Graph;
void Creat_graph(Graph * G)
{
    int i, j, m, n, q;
    scanf("%d %d", &G->vexnum, &G->arcnum);
    for(i = 0; i < G->vexnum; i++){
        G->vexs[i] = i;
    }
    for(i = 0; i < G->vexnum; i++){
        for(j = 0; j < G->vexnum; j++){
            G->arcs[i][j] = 99;
        }
    }
    for(i = 0; i < G->arcnum; i++){
        scanf("%d %d %d", &m, &n, &q);
        G->arcs[m][n] = q;
        G->arcs[n][m] = q;  //建立无向图
    }
}

int main()
{
    Graph G;
    Creat_graph(&G);
    
    int i, j;
    for(i = 0; i < G.vexnum; i++){
        for(j = 0; j < G.vexnum; j++){
            if(G.arcs[i][j] < 10)
                printf("%d      ", G.arcs[i][j]);
            else
                printf("%d     ", G.arcs[i][j]);
        }
        putchar('\n');
    } //输出
    
    return 0;
}

结果如下:

 

 

 

然后在根据权值生成最小生成树,代码如下:

#include<stdio.h>
#define MNUM 11
typedef struct
{
    int vexs[MNUM];  //这里把数字作为顶点的代表  如果是字母可以为char vexs[MNUM];
    int arcs[MNUM][MNUM];
    int vexnum, arcnum;
}Graph;
void Creat_graph(Graph * G)
{
    int i, j, m, n, q;
    scanf("%d %d", &G->vexnum, &G->arcnum);
    for(i = 0; i < G->vexnum; i++){
        G->vexs[i] = i;
    }
    for(i = 0; i < G->vexnum; i++){
        for(j = 0; j < G->vexnum; j++){
            if(i == j)
                G->arcs[i][j] = 0;
            else
                G->arcs[i][j] = 99;
        }
    }
    for(i = 0; i < G->arcnum; i++){
        scanf("%d %d %d", &m, &n, &q);
        G->arcs[m][n] = q;
        G->arcs[n][m] = q;  //建立无向图
    }
}

void MST_Prim(Graph G)
{
    int min, i, j, k;
    int adjvex[MNUM]; //保存相关连顶点的坐标
    int lowcost[MNUM] ; //保存相关连顶点之间的权值
    lowcost[0] = 0;
    /* 这里把lowcost为0的点标记为已经进入树中,
    在这里的lowcost[0] = 0的意思就是为V0已经加到树中了*/
    for(i = 1; i < G.vexnum; i++){//遍历全部顶点
        lowcost[i] = G.arcs[0][i];  //将与V0相关连的顶点之间的权值存入数组
        adjvex[i] = 0;  //初始化都变为V0的下标
    }
    for(i = 1; i < G.vexnum; i++){  //遍历全部顶点
        min = 99; //初始化最小的权值为99(这里的99只是针对于本题举得例题而言,相对于本题来说,可以把99看权值的无穷大)

        j = 1, k = 0;
        while(j < G.vexnum){ //遍历全部顶点
            if(lowcost[j] != 0 && lowcost[j] < min){
                min = lowcost[j];
                k = j;  //利用k来暂存
            }
            j++;
        }
        printf("%d --> %d \n", k, adjvex[k]);
        lowcost[k] = 0;// 将当前顶点的权值设置为0来表示此定点已经加入到最小生成树中了
        for(j = 1; j < G.vexnum; j++){
            if(lowcost[j] != 0 && G.arcs[k][j] < lowcost[j]){
                lowcost[j] = G.arcs[k][j];
                adjvex[j] = k;
            }
        }

    }

}

int main()
{
    Graph G;
    Creat_graph(&G);

    int i, j;
    for(i = 0; i < G.vexnum; i++){
        for(j = 0; j < G.vexnum; j++){
            if(G.arcs[i][j] < 10)
                printf("%d      ", G.arcs[i][j]);
            else
                printf("%d     ", G.arcs[i][j]);
        }
        putchar('\n');
    } //输出

    MST_Prim(G);//新添语句

    return 0;
}

结果为:

 

 

由此最小生成树的生成过程为:

 

最后最小生成树上的权值加和为花费的最少金钱。

 

 

如有不妥,欢迎批评指正

 

 

 

 

 

 

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值