• 最小生成树问题-prim算法求解


    MST(Minimum Spanning Tree,最小生成树)问题有两种通用的解法,Prim算法就是其中之一,它是从点 的方面考 虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到 V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最 小,此时将c点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一 个点,就意味着找到一条MST的边。

    代码如下:

    #include "stdio.h"    
    #include "stdlib.h"   
    #include "io.h"  
    #include "math.h"  
    #include "time.h"
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    #define MAXEDGE 20
    #define MAXVEX 20
    #define INFINITY 65535
    
    typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    
    typedef struct
    {
        int arc[MAXVEX][MAXVEX];
        int numVertexes, numEdges;    //节点数量与边的数量
    }MGraph;
    
    void CreateMGraph(MGraph *G)/* 构建图 */
    {
        int i, j;
    
        /* printf("请输入边数和顶点数:"); */
        G->numEdges=15;
        G->numVertexes=9;
    
        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] = G->arc[j][i] = 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];
            }
        }
    }
    
    /* Prim算法生成最小生成树 */
    void MiniSpanTree_Prim(MGraph G)
    {    
        int min, i, j, k;
        int adjvex[MAXVEX];        /* 保存相关顶点下标 */
        int lowcost[MAXVEX];    /* 保存相关顶点间边的权值 */
    
        //1.初始lowcost[]和adjvex[]数组
        lowcost[0] = 0;/* 初始化第一个权值为0,即v0加入生成树 */
                /* lowcost的值为0,在这里就是此下标的顶点已经加入生成树 */
        adjvex[0] = 0;            /* 初始化第一个顶点下标为0 */
        for(i = 1; i < G.numVertexes; i++)    /* 循环除下标为0外的全部顶点 */
        {
            lowcost[i] = G.arc[0][i];    /* 将v0顶点与之有边的权值存入数组 */
            adjvex[i] = 0;                    /* 初始化都为v0的下标 */
        }
    
        //2.从lowcost[]中找到最小权值
        for(i = 1; i < G.numVertexes; i++)
        {
            min = INFINITY;    /* 初始化最小权值为∞, */
                            /* 通常设置为不可能的大数字如32767、65535等 */
            j = 1;k = 0;
    
            //找出最小的权值及其所在的下标
            while(j < G.numVertexes)    /* 循环全部顶点 */
            {
                if(lowcost[j]!=0 && lowcost[j] < min)/* 如果权值不为0且权值小于min */
                {    
                    min = lowcost[j];    /* 则让当前权值成为最小值 */
                    k = j;            /* 将当前最小值的下标存入k */
                }
                j++;
            }
            //3.打印第一条权最小的边
            //adjvex[k]中存放较小权值所在的行,上面算得的k是较小权值所在的列
            printf("(%d, %d)
    ", adjvex[k], k);/* 打印当前顶点边中权值最小的边 */
            lowcost[k] = 0;
    
            //4.更新lowcost[],包含两个方面的更新
            /* 将当前顶点的权值设置为0,表示此顶点已经完成任务 */
            for(j = 1; j < G.numVertexes; j++)    /* 循环所有顶点 */
            {
                if(lowcost[j]!=0 && G.arc[k][j] < lowcost[j]) 
                {/* 如果下标为k顶点各边权值小于此前这些顶点未被加入生成树权值 */
                    lowcost[j] = G.arc[k][j];/* 将较小的权值存入lowcost相应位置 */
                    adjvex[j] = k;                /* 将下标为k的顶点存入adjvex */
                }
            }
        }
    }
    
    int main(void)
    {
        MGraph G;
        CreateMGraph(&G);
        MiniSpanTree_Prim(G);
      
        return 0;
     
    }


  • 相关阅读:
    Vue.js整理
    linux~dd命令
    linux 开机自启动的两种方式
    解决mount.nfs: access denied by server while mounting
    pip与apt-get的使用
    Mysql 中字符串的截取
    学生练习:括号匹配
    迷宫问题,打印所有路径,深度搜索,dfs
    vector用法
    【CF1257A】Two Rival Students【思维】
  • 原文地址:https://www.cnblogs.com/Allen-win/p/7346417.html
Copyright © 2020-2023  润新知