/*************************
普里姆(prim)算法 ****************************/#define m 6#define max 100 #include<stdio.h>#include<stdlib.h>int cost[m][m]={100, 6 ,1 , 5, 100, 100, //花费矩阵,即每一行的数据代表该行到图中各定点的权值 6,100,5, 100, 3, 100, 1, 5,100, 5, 6, 4, 5,100, 5, 100, 100,2, 100, 3, 6, 100,100, 6, 100,100, 4, 2, 6, 100};int lowcost[m],adjvex[m],s[m]; //其中lowcost数组是选中定点到图中顶点的最小权值 //adjvex数组存放的是到各个顶点的前驱顶点的位置 //s数组是标志数组,里面的0,1标志着顶点是否选中过. void prim(int n, int v0) //n是顶点个数. vo是初始顶点位置 { int w,i,j,k,u; for(w = 0; w < n; w++) { lowcost[w] = cost[v0][w]; //初始化lowcost数组,其初始值就为花费矩阵cost的第v0行的各个值 adjvex[w] = v0; //到各个顶点的前驱顶点就是v0 } for(w = 0; w < n; w++) s[w] = 0; //标志数组的初始化 s[v0] = 1; for(i = 1 ; i < n; i++) //由于连接n个点需要n-1条路径,故是i=1到i=n共n-1次循环 { int min = max; for(j = 0; j < n; j++) // 这个循环的作用是在lowcost数组里面寻找最小值.因为最小值对应的顶点就是下一个要选的顶点 { if(s[j] == 0 && lowcost[j] < min) { u = j; min = lowcost[j]; } }//循环过后,min里面就是lowcost数组里面最小的权值,而u就是最小权值对应的顶点位置也就是下一个要被选中的顶点 s[u] = 1; printf("%d---%d",adjvex[u],u); //输出路径 for(k = 0; k < n; k++) //这个循环是将上面选定的顶点u到各个顶点的权值与lowcost数组的对应权值进行比较,找出最小值进行替换 { if(s[k] == 0 && cost[u][k] < lowcost[k]) { lowcost[k] = cost[u][k]; adjvex[k] = u; } } printf("/n"); } }int main(){ prim(6,0); return 0;} /*************************************算法分析:普里姆算法实际上就是构造带有权值的图的最小生成树的算法.算法的最大的特点就是引用了三个辅助数组:(1)最小权值数组(lowcost),该数组里面存放的是已选中的顶点集中各个顶点到未被选中的顶点的最小权值.(2)路径存放数组(adjvex),该数组里面存放的是顶点集外的各顶点(还未被选中的顶点)到已选顶点集的哪个顶点权值最小,也就是放的是前驱 顶点(3)标志数组(s),该数组里面存放的是数组下标对应的各顶点是否被选中的标志,也就是说只存放0,1.算法思想:我们的目的是从一个顶点出发,寻找一条路径通过所有的顶点,而这条路径的限制是要求权值最小.于是,我们从一个顶点出发,不停向这个顶点集里面添加顶点(添加顶点的过程其实就是寻找路径的过程).而如何保证走的路径的权值是最小的呢?这里我们就引入了lowcost数组,来保存顶点集中的顶点到还未走过的顶点的权值大小.故只要遍历lowcost数组,通过选择排序(中间变量min)就能很轻松地找到权值最小的顶点(程序中的u).而这个顶点就是下一个要走的顶点.而由于不能走重复的顶点.故在排序比较的时候就要加上一个条件:这个顶点未走过.这样就需要引入标志数组(s).选中下一个顶点后,下一步动作就是什么呢?下一步动作就是继续寻找顶点,这里就需要更新lowcost数组的值了,因为这时的顶点集里面的顶点已经增加到2个了(lowcost里面的值是顶点集中的顶点到未选中顶点的权值最小值).于是通过一个循环将选中顶点的邻接矩阵里面的值与lowcost里面的值一一进行比较,找到更小的就进行替换.而顶点找到后,要如何输出走过的路径呢?这里需要引入的就是路径存放数组(adjvex).***************************************/