本算法以无向图为例,图的存储方式采用邻接矩阵
1)以第一个顶点开始本算法,将第一个顶点(i = 0)加入最小生成树集low_cost[i] = 0,0代表已经加入生成树集;
2)遍历第i行邻接矩阵,更新与顶点i有边的顶点的权值(该权值集的初始化值为与第一个顶点有边连接的顶点的权值)
3)遍历这个low_cost权值集合,找到最小权值并输出
为了找到与当前顶点有边的前一个顶点,算法用Vertex_Information[]进行了记录
我们先为左图构造邻接矩阵,如右图所示
算法从A点开始生成最小生成树,代码如下:
/********************************************************************* Author:tmw date:2017-10-17 ********************************************************************************************/ #include <stdio.h> #include <stdlib.h> #define MAX_VERTEX 100 #define inf 65535 //用65535代表无穷大 /*************************建立无向图邻接矩阵**************************/ typedef struct Matrix_Graph { char vertex[MAX_VERTEX];//存储顶点信息 int edge[MAX_VERTEX][MAX_VERTEX];//存储边信息 int vertex_number,edge_number;//存储图中的顶点数和边数 }Matrix_Graph; void create_non_direction_matrix_Graph( Matrix_Graph *G ) { int i,j,w,k; printf("请输入顶点数和边数:\n"); scanf("%d %d",&G->vertex_number,&G->edge_number); printf("请输入无向图顶点信息(如ABCD...):\n"); char ch; while( ( ch = getchar() ) != '\n' ); for( i = 0 ; i < G->vertex_number ; i++ ) scanf("%c",&G->vertex[i]); //初始化边信息 for( i = 0 ; i < G->vertex_number ; i++ ) for( j = 0 ; j < G->vertex_number ; j++ ) { if( i == j ) G->edge[i][j] = 0; else G->edge[i][j] = inf; } printf("请输入无向图中相连的两个顶点下标值(Vi,Vj),以及权值---即边信息\n"); for( k = 0 ; k < G->edge_number ; k++ ) { scanf("%d %d %d",&i,&j,&w); G->edge[i][j] = w; G->edge[j][i] = G->edge[i][j];//由于是无向图,故是对称阵 } //打印邻接矩阵 for( i = 0 ; i < G->vertex_number ; i++ ) { for( j = 0 ; j < G->vertex_number ; j++ ) printf("%d\t",G->edge[i][j]); printf("\n"); } } void Min_Create_Tree_Prim( Matrix_Graph *G ) { int i,j,min; int mark = 0; int low_cost[MAX_VERTEX]; int Vertex_Information[MAX_VERTEX];//便于找到权值最小边的前一个顶点 low_cost[0] = 0; //low_cost记录已经用于生成最小生成树的顶点,若为0,则标记为用过 //这里从第一个顶点开始生成最小生成树,因此首先标记它为0 for( i = 1 ; i < G->vertex_number ; i++ )//因为第一个顶点已经纳入生成树,因此从第二个顶点开始遍历 { low_cost[i] = G->edge[0][i];//将与第一个顶点有边相连的顶点权值放入low_cost数组 Vertex_Information[i] = 0; //初始化相关顶点的下标都从第一个顶点开始 } for( i = 1 ; i < G->vertex_number ; i++ ) { min = inf; j = 1; while( j < G->vertex_number )//找出与当前顶点权值最小的顶点 { if( low_cost[j]!=0 && low_cost[j] < min ) { min = low_cost[j]; mark = j;//将最小权值顶点做个标记 } j++; } low_cost[mark] = 0;//标记新加入顶点已经被加入生成树 printf("[%d %d] ---",Vertex_Information[mark],mark);//打印顶点下标号 printf("%c %c\n",G->vertex[Vertex_Information[mark]],G->vertex[mark]);//打印找到的当前顶点的最小权值边 //找 与当前顶点和新加入顶点中 还相连的其他顶点 for( j = 1 ; j < G->vertex_number ; j++ ) { if( low_cost[j] != 0 && low_cost[j] > G->edge[mark][j] )//更新 与当前顶点和新加入顶点间 其他与之相连顶点的权值 { low_cost[j] = G->edge[mark][j]; Vertex_Information[j] = mark;//标记边的第一个顶点 } } } } int main() { Matrix_Graph *G; G = (Matrix_Graph*)malloc(sizeof(Matrix_Graph)); create_non_direction_matrix_Graph(G); Min_Create_Tree_Prim(G); return 0; }
【程序执行结果】
从代码结果可看出,本次构造的最小生成树路径为:[A B]、[A F]、[B I]、[I C]、[B G]、[G H]、[H E]、[H D]