Prim最小生成树算法
对于带权连通无向图,它有许多生成树,但最有意义的是使得边权值最小的生成树,即最小生成树MST
Prim算法,类似于最短路径的Dijkstra算法。
初始时从图中任取一顶点加入树T,此时树中只含有一个顶点,之后选择一个与当前T中顶点集合距离最近的顶点,并将该顶点和相应的边加入T,每次操作后T中的顶点数和边数都增1。以此类推,直至图中所有的顶点都并入T。
void Prim(G, T){
T=NULL; // 初始化空树 注意T=(U,E),就是说U其实是T中的
U={w}; // 添加任一顶点w
while((V-U)!=NULL){ // 若树中不含全部顶点
找(u,v)是使u∈U与v∈(V-U),且权值最小的边;
T=T∪{(u,v)}; // 边归并入树中
U=U∪{v}; // 顶点归入树中
}
}
bool visited[MaxVertexNum]; // 访问标记数组
void Prim(MGraph G, int v) { // Prim 最小生成树算法 v为起点
int min_weight = 0; // 最小代价
int distance[MaxVertexNum]; // 记录当前集合中的点与不在集合中点的最小距离
VertexType to_Print[MaxVertexNum]; // 顺序记录加入集合中的点
int w=v, i; //选中的顶点
to_Print[0] = G.Vex[w];
for (i = 0; i < G.vexnum; i++) { // 初始化
visited[i] = false;
distance[i] = G.Edge[w][i] != INITIAL_VALUE ? G.Edge[w][i] : INT_MAX;
}
visited[w] = true; // 不再访问
int count = 0; // 执行n-1次,获取n-1条边
while ( (count++) < G.vexnum - 1) {
int min = INT_MAX;
for (i = 0; i < G.vexnum; i++) { // 选出最小边
if (!visited[i] && distance[i] < min) {
min = distance[i];
w = i;
}
}
visited[w] = true; // 不再访问
to_Print[count] = G.Vex[w];
min_weight += min;
for (i = 0; i < G.vexnum; i++) { // 更新distance数组
if (!visited[i] && G.Edge[w][i] < distance[i])
distance[i] = G.Edge[w][i];
}
}
cout << min_weight << endl;
for (i = 0; i < count; i++) {
printf("%c \t", to_Print[i]);
}
}