Prim算法构造最小生成树过程如下图所示:
1、首先从图中任选一个顶点加入树T中,此时最小生成树T中就只含有一个顶点
2、然后选择与当前最小生成树T中顶点集合距离最近的顶点,并将该顶点和相应的边加入最小生成树T中,每次操作树T中的顶点数量和边都加一。
3、执行1,2两步,当图中的所有顶点都并入到T中,T就是最小生成树了。此时T中必有n-1条边
1、先初始化辅助数组,即从起始点到其他顶点的权值保存到数组中,并标志起始点
2、循环执行以下操作(循环次数为图中顶点的数量减一,因为起始点不算)
(1)、定位数组中权值最小的权值,从而找到对应的下一个要加入的顶点。
(2)、在辅助数组中将新加入的顶点的权值置为0(自己到自己的距离为0)
(3)、跟新辅助数组,在新加入定点之后,集合T中的顶点到其他顶点的最小距离会变化,所以跟新新加入的顶点到其他顶点的距离,如果比原来的小,则跟新,否则不跟新。
#ifndef DATASTRUCTURE_MST_H #define DATASTRUCTURE_MST_H #include <stdio.h> #include "../Graph/Graph.h" //#include "../Graph/Graph.c" //生成树的类型定义 typedef struct { VertexType adjvex; //较早加入当前集合T的顶点(权值最小边的起始点) VRType lowcost; //以该顶点为起始点的边的权值 }Edge; //辅助数组 typedef Edge closeEdge[MAX_VERTEX_NUM]; //创建一个辅助数组,表示已经加入到T中集合的顶点到其他顶点的最近距离 //在辅助数组中找到权值最小的边的数组下标 int Minimum(MGraph G,closeEdge close); //普里母算法 void MinSpanTree_Prim(MGraph G,VertexType v); #endif //DATASTRUCTURE_MST_H
#include "MST.h" /** * 普利姆算法 * @param G 无向网 * @param v 开始顶点(随意) 初始为顶点1 */ void MinSpanTree_Prim(MGraph G,VertexType v){ int k = LocateVex(G,v); closeEdge close; //辅助数组 //初始化辅助数组,将与该起始点有关的所有边的信息:边的起始点和权值,初始化到辅助数组中 //如初始顶点为1,那么有顶点1相连的有顶点2,3,4,则顶点1到2,3,4为其边上的权值,而与顶点5,6不相邻,所以为INFINITY //其中辅助数组的大小为图中顶点的数量,因此对应起始点与图中顶点的权值,即close[i].adjvex表示的是起始顶点,i对应的是顶点在 //G中顶点数组的下标,所以可以通过i来找到顶点值 for (int i = 0; i < G.vexnum; ++i) { if (i!=k){ close[i].adjvex = k; close[i].lowcost = G.arcs[k][i].adj; } } //因为起始点已经在最小生成树中了,所以需要将其辅助数组置0,或者因为从该点开始的,所以距离为0 close[k].lowcost = 0; //选择下一个点,并更新辅助数组中的信息 for (int i = 1; i < G.vexnum; ++i) { //为什么从1开始,因为目前已经有一个在最小生成树中了 k = Minimum(G,close); //找到权值最小的边所在数组的下标 printf("v%d \t v%d\t",G.vexs[close[k].adjvex],G.vexs[k]); //输出选择的路径 close[k].lowcost = 0; //入树之后需要将权值设置为0 //因为加入了一个顶点,那么辅助数组中的权值可能就会发生改变,所以,需要从新加入的顶点开始,比较其到其他邻接顶点的权值 //如果小的就需要更新 for (int j = 0; j < G.vexnum; ++j) { if (G.arcs[k][j].adj<close[j].lowcost){ close[j].lowcost = G.arcs[k][j].adj; close[j].adjvex = k; } } printf("\n"); } } //在辅助数组中找到权值最小的边的数组下标 int Minimum(MGraph G,closeEdge close){ int min = INFINITY; //为无向网,所以INFINTIY表示最大距离 int index; for (int i = 0; i < G.vexnum; ++i) { if (close[i].lowcost>0&&close[i].lowcost<min){ //当权值为0的时候,说明顶点已经归到了最下生成树中了 min = close[i].lowcost; index = i; } } return index; } /** * 确定顶点v在图中的位置 * @param G * @param v 为顶点值 * @return 如果在图的顶点数组中找到,则返回在数组中的下标,否则返回-1; */ int LocateVex(MGraph G,VertexType v){ for (int i = 0; i < G.vexnum; ++i) { if (v == G.vexs[i]){ return i; } } return -1; }