【最小生成树】prim算法
算法分析的一般步骤:
1、文字描述:如果一个算法文字描述不清楚,就说明思路不清楚,也不可能写好。
prim算法是实现图的最小生成树。既然是图,就假设包含n个顶点,m条边。prim算法是从顶点出发的,其算法时间复杂度与顶点数目有关系。
(注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。)
算法思路:从某个顶点开始,假设v0,此时v0属于最小生成树结点中的一个元素,该集合假设u,剩下的V-v0为待判定的点,此时选取u中的顶点到V-v0中顶点的一个路径最小的边,并且将其中非u中的顶点加入到u中,循环直到u中的顶点包含图所有的顶点为止。
算法在选取最小路径的时候需要优化,具体思路:w[]数组保存各个顶点的最短路径,b[]数组保存到i顶点最短路径的顶点,比如,到0号顶点最短的路径是<v0,v3>,那么w[0]=<v0,v3>,b[0]=3;这样每次找最小路径就不是o(n*n)的代价了。
2、举例说明:
3、程序实现与说明:
#include <stdio.h> #include <stdlib.h> #define count 6 void prim(int a[][count],int u[],int w[],int b[],int n) { int i=0,j=0,m=0,min=100; for(i=0;i<count;i++) { u[i]=0;//初始化0,说明没有访问过 w[i]=a[0][i];//初始每个顶点最短路径为到0顶点的距离 b[i]=0;//初始每个顶点都指向0顶点 } u[0]=1;//赋值1,从0顶点开始 for(i=1;i<n;i++) { min=100; j=0; for(m=1;m<n;m++) { if(!u[m] && w[m]<min)//很关键,得到到访问顶点到未访问顶点的最短路径以及对应顶点j { min=w[m]; j=m; } } u[j]=1;//把下一个顶点标为已访问 printf("%d,%d\n",j+1,b[j]+1);//输出结果 for(m=1;m<n;m++) { if(!u[m] && a[j][m]<w[m])//此时,u集合里面多了一个顶点j,要重新更新最短路径以及对应的顶点 { w[m]=a[j][m]; b[m]=j; } } } } int main() { int u[count],w[count],b[count],a[count][count]; int i=0,j=0; for(i=0;i<count;i++) { for(j=0;j<count;j++) { a[i][j]= 100; } } a[0][1]=6,a[0][2]=1,a[0][3]=5; a[1][0]=6,a[1][2]=5,a[1][4]=3; a[2][0]=1,a[2][1]=5,a[2][3]=5,a[2][4]=6,a[2][5]=4; a[3][0]=5,a[3][2]=5,a[3][5]=2; a[4][1]=3,a[4][2]=6,a[4][5]=6; a[5][3]=2,a[5][2]=4,a[5][4]=6; prim(a,u,w,b,count); return 0; }
4、时间复杂度:o(n*n)
参考博客:https://www.cnblogs.com/nannanITeye/p/3446424.html