基于C语言的最小生成树--普里姆算法

普里姆算法(prim)

普里姆算法建立在邻接矩阵的基础之上,我们用65535来表示INFINITY,表示两个顶点之间没有关联。0表示自身,其他的数表示权值。
矩阵表示

代码实现及讲解:

#define max 100
#define INFINITY 65535
typedef struct
{
	char vex[max];
	int arc[max][max];
	int vexnum , edgenum ;
}MGraph;

void MGraph_init(MGraph *G)   // 初始化图
{
	printf("请输入顶点数和边数");
	scanf_s("%d %d", &G->vexnum, &G->edgenum);
	for (int i = 0; i < G->vexnum; i++) // 初始化顶点信息
	{
		printf("请输入顶点信息");
		scanf_s(" %c", &G->vex[i]);
	}

	for (int i = 0; i < G->vexnum; i++) //初始化指向 0表示不指向,1表示指向
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arc[i][j] = INFINITY; // 默认为不指向
			G->arc[i][0] = 0;
		}
	}

	int i, j, w;
	for (int k = 0; k < G->edgenum; k++) // 初始化各各顶点的指向
	{
		printf("输入(vi,vj)的下标i,j和指向w \n");
		scanf_s("%d %d %d", &i, &j, &w);
		G->arc[i][j] = w;
		G->arc[j][i] = G->arc[i][j]; // 因为在矩阵中,他们是对称的

	}

	for (int y = 0; y < G->vexnum; y++)  //打印二维数组
	{
		for (int u = 0; u < G->vexnum; u++)
		{
			printf("%d,", G->arc[y][u]);
		}
		printf("\n");
	}

}

// 普里姆算法实现
void Prim(MGraph G)
{
	int i, j, k, min;
	int lowcost[max], adjvex[max]; // lowcost用于储存权值,adjvex用于储存顶点的下标
	lowcost[0] = 0; // 表示将第一个V0顶点放入最小生成树中
	adjvex[0] = 0;
    
	for (i = 1; i < G.vexnum; i++)
	{
		lowcost[i] = G.arc[0][i]; // 将权值赋给lowcost
		adjvex[i] = 0;
	}
	for (i = 1; i < G.vexnum; i++)
	{
		min = INFINITY;

		j = 1;
		k = 0;
		while (j < G.vexnum)
		{
			if (lowcost[j] != 0 && lowcost[j] < min) // 不断的循环,找出权值的最小值,并且赋值给min,k做为最小值的下标
			{
				min = lowcost[j];
				k = j;
			}
			j++;
		}
		printf("top = (%d,%d),wight = %d\n", adjvex[k], k, min); // 打印最小生成树的顶点
		lowcost[k] = 0;
		for (j = 1; j < G.vexnum; j++)
		{
			if (lowcost[j] != 0 && G.arc[k][j] < lowcost[j])
			{
				lowcost[j] = G.arc[k][j];
				adjvex[j] = k; // 将最小值顶点的下标存入adjvex

			}
		}
		
		

	}

}

int main()
{
	MGraph G;
	MGraph_init(&G);
	Prim(G);
}

//测试样例
//typedef struct
//{
//	char vex[max] = { 'A','B','C','D','E','F','G','H','I' };
//	int arc[9][9] = { 0, 10,65535,65535,65535,11,65535,65535,65535,
//							10,65535,18,65535,65535,65535,16,65535,12,
//							0,18,65535,22,65535,65535,65535,65535,8,
//							0,65535,22,65535,20,65535,24,16,21,
//							0,65535,65535,20,65535,26,65535,7,65535,
//							11,65535,65535,65535,26,65535,17,65535,65535,
//							0,16,65535,24,65535,17,65535,19,65535,
//							0,65535,65535,16,7,65535,19,65535,65535,
//							0,12,8,21,65535,65535,65535,65535,65535 }; // 测试样例
//	int vexnum = 9, edgenum = 15;
//}MGraph;



**初始化代码后,lowcost用于储存最小生成树的边权值,adjvex储存最小生成树的顶点下标 **

刚开始默认将V0做为最小生成树的根结点,并且将V0边上的权值加载到lowcost上,lowcoast的下标表示的与V0相连接的顶点,k用于储存最小值顶点下标,adjvex储存的是两个顶点之间的关系,如adjvex[8] = 1 表示是从顶点1 指向顶点8。

第一次运行,lowcost初始化后 lowcost={0,10,65535,65535,65535,11,65535,65535,65535},循环遍历

  • lowcost中的最小值,min =10,k=1 因为adjvex[1] = 0,表示从(0,1),之后打印(0,1)和权值

    在这里插入图片描述

  • 之后让lowcost[k] = 0,表示这个顶点已经访问过,防止二次访问,之后如果图中G.arc[k][j]<lowcost[j],表示的是将最小值顶点的边权值导入到lowcost中,如果G.arc[k][j],中的下标比lowcost的小,就替换lowcost[j]的值

  • 第二次中的lowcost= {0,0,18,65535,65535,11,16,65535,12},adjvex = {0,0,1,0,0,0,1,0,1}.

在这里插入图片描述

后面到的运行同理:

在这里插入图片描述

posted @ 2020-03-14 13:01  小白认证  阅读(170)  评论(0)    收藏  举报