//普里姆算法
//构造连通网的最小代价生成树
/*
基本思路:
1. 任选一个结点,任选一个作为这棵树的起点。
2. 找出所有与当前树中叶子结点连接的边,找出权最小的一条边,
将这条边的另一个端点加入到树中。
3. 重复2的操作,直到连接所有结点。
重点:
1.lowcost数组里保存的是与“当前树中所有叶子节点”有连线的未加入树的结点
2.adjvex数组:体会函数中的“printf("(%d, %d)\n", adjvex[k], k);”
*/
#include <stdio.h>
#define MAXNUM 9 //顶点的最大数量
#define INFINITY 65535
typedef struct {
char vexs[MAXNUM]; //包含所有顶点的数组
int arc [MAXNUM][MAXNUM]; //邻接矩阵
int numVertexes, numEdges; //当前图中的顶点数量和边的数量
} Graph;
//建立无向图的邻接矩阵
void CreatGraph(Graph* G) {
int i, j;
/*
printf("请输入顶点数和边数");
scanf("%d", &G->numVertexes);
scanf("%d", &G->numEdges);
for (i = 0; i < G->numVertexes; i++)
for (j = 0; j < G->numVertexes; j++)
G->arc[i][j] = INFINITY;
for (k = 0; k < G->numEdges; k++) {
printf("请输入边在邻接矩阵中的横纵坐标和权值:");
fflush(stdin);
scanf("%d", &i);
scanf("%d", &j);
scanf("%d", &w);
G->arc[i][j] = w;
G->arc[j][i] = G->arc[i][j];
}
*/
G->numVertexes = 9;
G->numEdges = 15;
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] = 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];
}
}
printf("\n该邻接矩阵是\n");
for (i = 0; i < G->numVertexes; i++) {
for (j = 0; j < G->numVertexes; j++)
printf("%5d ", G->arc[i][j]);
printf("\n");
}
}
//普里姆算法生成最小生成树
void MiniSpanTree_Prim(Graph G) {
int min, i, j, k;
int lowcost[MAXNUM];//保存相关顶点之间边的权值
int adjvex[MAXNUM];//保存相关顶点下标
lowcost[0] = 0;
adjvex[0] = 0;//第一个顶点下标为0
for (i = 1; i < G.numVertexes; i++) {//循环搜索除下标0外的全部顶点
lowcost[i] = G.arc[0][i];//将与V0顶点有关的顶点的边的权值存入数组
adjvex[i] = 0;//全部初始化为0的下标
}
for (i = 1; i < G.numVertexes; i++) {
min = INFINITY;//将最小值初始化为“无限大”
j = 1; k = 0;
//这个while循环最终找到的是与当前叶节点距离最近的顶点的下标值(存入k)
while (j < G.numVertexes) {
if (lowcost[j]!=0 && lowcost[j]<min) {
min = lowcost[j];
k = j;
}
j++;
}
//在最小生成树中,adjvex[k]节点为k节点的父节点
printf("(%d, %d)\n", 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;
//注意:意思是新加入候选节点的j节点(们)是当前加入树的k节点的孩子节点
}
}
}
}
int main()
{
Graph G;
CreatGraph(&G);
MiniSpanTree_Prim(G);
return 0;
}