prim算法
prim算法是求最小生成树,这个算法的基本思路就是我从v0 开始找到跟v0 连接的所有边,找到权重最小的边以及跟这个边相连的顶点Vx,然后依次查找V0和Vx相邻的边中权重最小的,把相连的顶点加入。
在写程序的时候,我们有几点技巧可以使用。
1、跟v0相连的边的权重以及跟Vx相连边的权重都是顶点数减1,这样我们在保存权重的时候,就可以直接构建一个数组保存当前顶点跟所有其他相连边的权重中小的,具体的讲就是一开始我保存v0跟其他边相连的权重,接下来我们确定了Vx,那把Vx跟其他边相连的权重依次跟v0与其他边相连的权重相比,如果小则替换,再在这个里面找最小值。把这个相连顶点跟边加入。
2、因为不能有回路,我们加入的顶点我们要标识一下,而这个我们仍然可以用上面的数组,即我们已经加入的顶点的下标所对应的上述数组设为0,意思我们找到了这个顶点,这样我们下面在处理的时候,我们首先判断一下这个顶点是不是已经加入。
具体的代码如下:
#include <stdio.h> #define MAXVEX 20 #define INFINITY 65535 typedef struct { int arc[MAXVEX][MAXVEX]; int numVertexes, numEdges; }MGraph; void CreateMGraph(MGraph *g) { int i, j; 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]; } } } void minSpanTreePrim(MGraph g) { int min,i,j,k; int adjvex[MAXVEX];//保存顶点下标 int lowcost[MAXVEX];//保存相关顶点间边的权值 lowcost[0]=0;//把第一个点加入后其跟自己的权值为0 adjvex[0]=0;//把第一个点加入 //先初始化,将跟第一个点有关联的边加入 for(i=1;i<g.numVertexes;i++) { lowcost[i]=g.arc[0][i]; adjvex[i]=0; } //找到最小权值的边 for(i=1;i<g.numVertexes;i++) { min = INFINITY; for(j=1;j<g.numVertexes;j++) { if(lowcost[j]!=0 && lowcost[j]<min) { min = lowcost[j]; k=j; } } printf("(%d,%d)",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; } } } } int main() { MGraph g; CreateMGraph(&g); minSpanTreePrim(g); }