普里姆算法

//普里姆算法
//构造连通网的最小代价生成树
/*
基本思路:
    1. 任选一个结点,任选一个作为这棵树的起点。
    2. 找出所有与当前树中叶子结点连接的边,找出权最小的一条边,
         将这条边的另一个端点加入到树中。
    3. 重复2的操作,直到连接所有结点。
重点:
    1.lowcost数组里保存的是与“当前树中所有叶子节点”有连线的未加入树的结点
    2.adjvex数组:体会函数中的“printf("(%d, %d)\n", adjvex[k], k);”
*/
#include <stdio.h>
#define MAXNUM 9                 //顶点的最大数量
#define INFINITY 65535

typedef struct {
    char vexs[MAXNUM];             //包含所有顶点的数组
    int arc [MAXNUM][MAXNUM];      //邻接矩阵
    int numVertexes, numEdges;      //当前图中的顶点数量和边的数量
} Graph;

//建立无向图的邻接矩阵
void CreatGraph(Graph* G) {
    int i, j;
/*
    printf("请输入顶点数和边数");
    scanf("%d", &G->numVertexes);
    scanf("%d", &G->numEdges);

    for (i = 0; i < G->numVertexes; i++)
        for (j = 0; j < G->numVertexes; j++)
            G->arc[i][j] = INFINITY;

    for (k = 0; k < G->numEdges; k++) {
        printf("请输入边在邻接矩阵中的横纵坐标和权值:");
        fflush(stdin);
        scanf("%d", &i);
        scanf("%d", &j);
        scanf("%d", &w);
        G->arc[i][j] = w;
        G->arc[j][i] = G->arc[i][j];
    }
*/
    G->numVertexes = 9;
    G->numEdges = 15;

    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] = INFINITY;
        }
    G->arc[0][1]=10;
    G->arc[0][5]=11;
    G->arc[1][2]=18;
    G->arc[1][8]=12;
    G->arc[1][6]=16;
    G->arc[2][8]=8;
    G->arc[2][3]=22;
    G->arc[3][8]=21;
    G->arc[3][6]=24;
    G->arc[3][7]=16;
    G->arc[3][4]=20;
    G->arc[4][7]=7;
    G->arc[4][5]=26;
    G->arc[5][6]=17;
    G->arc[6][7]=19;

    for(i = 0; i < G->numVertexes; i++) {
            for(j = i; j < G->numVertexes; j++) {
                G->arc[j][i] =G->arc[i][j];
            }
        }

    printf("\n该邻接矩阵是\n");
    for (i = 0; i < G->numVertexes; i++) {
        for (j = 0; j < G->numVertexes; j++)
            printf("%5d ", G->arc[i][j]);
        printf("\n");
    }

}

//普里姆算法生成最小生成树
void MiniSpanTree_Prim(Graph G) {
    int min, i, j, k;
    int lowcost[MAXNUM];//保存相关顶点之间边的权值
    int adjvex[MAXNUM];//保存相关顶点下标
    lowcost[0] = 0;
    adjvex[0] = 0;//第一个顶点下标为0
    for (i = 1; i < G.numVertexes; i++) {//循环搜索除下标0外的全部顶点
        lowcost[i] = G.arc[0][i];//将与V0顶点有关的顶点的边的权值存入数组
        adjvex[i] = 0;//全部初始化为0的下标
    }

    for (i = 1; i < G.numVertexes; i++) {
        min = INFINITY;//将最小值初始化为“无限大”
        j = 1; k = 0;
        //这个while循环最终找到的是与当前叶节点距离最近的顶点的下标值(存入k)
        while (j < G.numVertexes) {
            if (lowcost[j]!=0 && lowcost[j]<min) {
                min = lowcost[j];
                k = j;
            }
            j++;
        }
        //在最小生成树中,adjvex[k]节点为k节点的父节点
        printf("(%d, %d)\n", adjvex[k], k);
        lowcost[k] = 0;//此顶点已在树中了,所以不再考虑它了
        for (j = 1; j < G.numVertexes; j++) {
            if (lowcost[j]!=0 && G.arc[k][j] < lowcost[j]) {
                lowcost[j] = G.arc[k][j];
                adjvex[j] = k;
        //注意:意思是新加入候选节点的j节点(们)是当前加入树的k节点的孩子节点
            }
        }
    }
}
int main()
{
    Graph G;
    CreatGraph(&G);
    MiniSpanTree_Prim(G);

    return 0;
}

转载于:https://www.cnblogs.com/qianbixin/p/4998347.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值