最小连通网

#include <stdio.h>

#define  NUM  9 //顶点数
#define  MV  65536 //最大值


int p[NUM];//辅助数组,记录边的数组,下标是一个顶点,值又是另一个顶点
int cost[NUM];//记录每条边的权值
int mark[NUM];//标记数组(标记是否被标记)

/*用邻接矩阵定义图,每个元素的数字代表相应边的权值,且注意邻接矩阵具有对称性*/
int matrix[NUM][NUM] =
{
	{ 0, 10, MV, MV, MV, 11, MV, MV, MV },
	{ 10, 0, 18, MV, MV, MV, 16, MV, 12 },
	{ MV, 18, 0, 22, MV, MV, MV, MV, 8 },
	{ MV, MV, 22, 0, 20, MV, MV, 16, 21 },
	{ MV, MV, MV, 20, 0, 26, MV, 7, MV },
	{ 11, MV, MV, MV, 26, 0, 17, MV, MV },
	{ MV, 16, MV, MV, MV, 17, 0, 19, MV },
	{ MV, MV, MV, 16, 7, MV, 19, 0, MV },
	{ MV, 12, 8, 21, MV, MV, MV, MV, 0 },
};
/*以sv为起始顶点开始寻找最小联通网*/
void Prim(int sv)
{
	int i = 0;//循环控制变量
	int j = 0;

	if ((0 <= sv) && (sv < NUM)){//合法性检测

		for (i = 0; i < NUM; i++){//初始化,以sv为起点到其他顶点的权值为cost数组赋值
			cost[i] = matrix[sv][i];
			p[i] = sv;//以sv出发,即值是一个顶点,且其他的i,即下标又是另一个顶点
			mark[i] = 0;//0表示没有被标记
		}

		mark[sv] = 1;//将选定的起始顶点先标记


		for (i = 0; i < NUM; i++){//重复找最小权值的边
			int min = MV;
			int index = -1;
			for (j = 0; j < NUM; j++){//真正以某一个顶点为起点找与之关联的最小权值的边
				if ((!mark[j]) && (cost[j] < min)){//如果没有被标记,且以sv作为起始顶点到其他定点的边的权值小于min
					min = cost[j];
					index = j;//以sv为起点找到的最小权值的边,另一顶点为index
				}
			}

			if (index > -1){//找到最小值
				mark[index] = 1;//标记该顶点

				printf("(%d,%d,%d)\n", p[index], index, cost[index]);//打印找到的边
			}
			/*修改cost数组,因为要从新顶点出发看看是否能找更小的权的边*/
			for (j = 0; j < NUM; j++){
				/*用刚刚标记的顶点index作为起始顶点和那些未标记的顶点去找权值最小的边,
				如果matrix[index][j] 小于ocst[j]成立,表示有可能能找到比当前cost记录的权值还要小的边,
				所以更新cost使之保持最小的权值*/
				if ((!mark[j]) && (matrix[index][j] < cost[j])){
					cost[j] = matrix[index][j];
					p[j] = index;//更新边的两个顶点
				}
			}

		}
	}


}

int main()
{
	Prim(0);
	
	system("PAUSE");
	return 0;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值