Prim算法生成最小生成树

一.先看代码:

# include <stdio.h>
# include <stdlib.h>

# define max 20
# define INEF 9999999


//邻接矩阵 
typedef struct node
{
    int  vexnum;//顶点的个数 
    int arcnum;//边的个数 
    int arcs[max][max];
    char vex[max];//存放定点的信息 
}NODE, *PNODE;


//标志数组 
typedef struct dd
{
    int adjvex;//存放与顶点权值小的顶点下标 
    int lowcost;//存放权值 
}LL;
LL closedge[max];


PNODE creat()//创建一个邻接矩阵 
{
    int i, j;
   PNODE G;
   char enter;
   printf("请输入定点的个数和边数:\n");
   scanf("%d%d",&G->vexnum,&G->arcnum);
   for(i = 1; i<=G->vexnum; i++)//初始化二维数组 
   {
       for( j = 1; j<=G->vexnum; j++)
       {
          G->arcs[i][j] = INEF;     
      }
   }
   printf("请你输入定点信息:\n");
   for(i = 1; i<=G->vexnum; i++)//初始化顶点的坐标 
   {
      scanf("%c%c",&enter, &G->vex[i]);
   }
    printf("请输入边的信息(a,b,w)w为边的权值\n");
    for(i = 1; i<=G->arcnum; i++)//存放相应有权值的相应的坐标 
    {
        int a,b,w;
        scanf("%d%d%d",&a,&b,&w);
        G->arcs[a][b] = w;
    }
    return G;
}



void Prim(PNODE G, int start)
{   
    char s1,s2;
    int i, e, k, m, min;
    closedge[start].lowcost = 0;
    s1 = G->vex[start];
    printf("%c ", s1);
    for(i = 1; i<=G->vexnum; i++)//给标志数组初始化为从出发点到每一个点(除自己外的)的权值 
    {
        if(i !=start)
        {
            closedge[i].adjvex = start;//标志出发顶点的下标 
            closedge[i].lowcost = G->arcs[start][i]; 
        }
    }
    for(e = 1; e<G->vexnum; e++)
    {
        min = INEF;
        for(k = 1; k<=G->vexnum; k++)//在标志数组中找到从出发点到其他点权值最小的下标, 这就是下次要走的路 
        {
            if(closedge[k].lowcost != 0 && closedge[k].lowcost < min)
            {
                min = closedge[k].lowcost;
                m  = k;
            }
        }

        printf("%c ",G->vex[m]);//输出最近的一个点的坐标 
        closedge[m].lowcost = 0;//将该点的标志记为访问过 

        for(i = 1; i<=G->vexnum; i++)//用新的顶点来重新初始化各顶点边的权值 
        {
            if((i!=m) && G->arcs[m][i]<closedge[i].lowcost) 
            {
               closedge[i].lowcost = G->arcs[m][i];
               closedge[i].adjvex = m; 
            }
        }
    }
}

int main(void)
{
    PNODE G = creat();
    Prim(G, 1);
    return 0;
} 

二.基本思想:

从连通网中的一个顶点出发,选择与它关联权值最小的边,将其的顶点加入到生成树的顶点集合u中,以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择最小的边,并将它的顶点加入到集合U中,如此下去,直到所有的顶点全都加入到生成树的顶点集合U中。

三.具体实现:

1:先建立一个邻接矩阵将图中的所有的顶点以及权值的信息都存放起来,然后,在创建一个结构体数组作为标志,
数组元素的下标对应与邻接矩阵中顶点的下标。然后选择一个顶点出发,输出它的信息并将它标志为已访问,
然后从邻接矩阵中找出从这个点到其他除自己之外所有顶点的路径长度。赋值给标志数组中的lowcost。
2:然后在这个标志数组中根据lowcost找出从离这个出发点距离最小的边的值,以及顶点的下标。
3:现在到了关键的时刻,输出你刚才找到那个顶点的下标,并且根据下标将标志数组中的lowcost赋值为0表示该顶点已经访问过,
然后在邻接矩阵中找出该顶点到其他所有顶点的权值,与已经走过顶点到其他没有走过顶点的权值(这个值记录在标志数组中)进行比较,

小知识

1:为什么要用邻接矩阵存?
因为整个算法通过比较标志数组元素确定代价最小的边,prim的时间复杂度为O(n2),它取决于顶点的个数所以,它更适合于,顶点少边多的情况(稠密图).

例如:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值