C语言Kruskal算法求最小生成树

Kruskal算法求出最小生成树。

图形

算法描述

先找最小权值边为1的边有(V1,V4),(V2,V9),保证不产生回路就可以成功选择边

除去上一次找的边后,在找权值最小的边为2的有(V2,V3),(V4,V3),(V5,V6),(V9,V8),连接不产生回路的边

除去之前找过的边,后面再看权值最小的边为3的边有(V1,V3),(V7,V8),(V9,V7)

按顺序判断(V1,V3)边会产生回路排除,(V7,V8)可选边,当连接完(V7,V8)后判断(V9,V7)连接会造成回路排除

排除找过的边后,找下一个权值最小的为4的边有(V6,V7),(V9,V6)

顺序判断,( V6,V7)符合,连接完(V9,V6)判断连接(V9,V6)是回路不符合

完成所以点相连结束

有N个点,最小生成树有N-1个边


C语言Kruskal算法实现
c 复制代码
//C语言Kruskal算法实现
#include<stdio.h>
#define M 1000//M表示无穷用1000代替
#define N 9 //N行N列的矩阵

void loop(int arr[N][N],int dot,int c[N])
{
	int i;
	for ( i = 0; i < N; i++)
	{
		if (arr[dot][i] == 1)
			c[i] = i + 1;
	}
}
//标记和判断是否为回路,不是回路返回1,是回路反回0
int Is(int arr[N][N], int row, int column)
{

	if (arr[row][column] == 0 || arr[column][row] == 0)
	{
		int a[N] = { 0 };
		int b[N] = { 0 };
		loop(arr, row, a);
		loop(arr, column, b);
		int flag = 1;
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				if (a[i] == b[j] && a[i] !=0)
					flag = 0;
			}
		}
		//没产生回路标记1
		if(flag)
		{ 
			arr[row][column] = 1;
			arr[column][row] = 1;
			return 1;
		}
		//产生回路标记-1	
		else
		{
			arr[row][column] = -1;
			arr[column][row] = -1;	
		}
	}
		return 0;
}
int main()
{
	//把上图权值对应值写成邻接阵
	int map[N][N] =
	{
		{M,6,3,1,M,M,M,M,M},
		{6,M,2,M,M,M,M,M,1},
		{3,2,M,2,M,M,M,M,M},
		{1,M,2,M,10,M,M,M,M},
		{M,M,M,10,M,2,M,M,6},
		{M,M,M,M,2,M,4,M,4},
		{M,M,M,M,M,4,M,3,3},
		{M,M,M,M,M,M,3,M,2},
		{M,1,M,M,6,4,3,2,M}
	};

	int arr[N][N] = { 0 };//用来标记边
	int count = 0;//用来记录边的数量,最小生成树的边为数N-1
	int i = 0, j = 0;
	int min = M;//记录最小权值
	int value = 0;//当前要找的最小权值
	int sum = 0;//记录总权值

	//打印
	printf("最小生成树连接的边分别为:\n");
	while (1)
	{
		min = M;//每次把最小权设置为最大
		//找权值最小边,和最小权值边的数量
		for (i = 0; i < N; i++)
		{
			for (j = 0; j < N; j++)
			{
				if (map[i][j] < min && map[i][j] > value)//判断是否为最小权
				{
					min = map[i][j];
				}
			
			}
		}
		value = min;
		//根据前面循环得到最小权值边,标记不构成回路的边
		for (i = 0; i < N; i++)
		{
			for (j = 0; j < N; j++)
			{
				if (map[i][j] == min && Is(arr, i, j))
				{
					//打印
					printf("权值为%d,连接V%d,V%d\n", value, i + 1, j + 1);
					sum += min;
					count++;
					if (count == (N - 1))
						break;
				}
			}
			if (count == (N - 1))
				break;
		}
		
		//找够边数跳出循环
		if (count == (N - 1))
			break;
	}
	printf("最小生成树的权值总和为:%d\n",sum);
	return 0;
}
相关推荐
神里流~霜灭2 分钟前
(C++)数据结构初阶(顺序表的实现)
linux·c语言·数据结构·c++·算法·顺序表·单链表
一只乔哇噻23 分钟前
java后端工程师进修ing(研一版 || day41)
java·开发语言·学习·算法
愚润求学25 分钟前
【贪心算法】day7
c++·算法·leetcode·贪心算法
要开心吖ZSH1 小时前
软件设计师备考-(十六)数据结构及算法应用(重要)
java·数据结构·算法·软考·软件设计师
带娃的IT创业者1 小时前
如何开发一个教育性质的多线程密码猜测演示器
网络·python·算法
草莓熊Lotso1 小时前
【C++】递归与迭代:两种编程范式的对比与实践
c语言·开发语言·c++·经验分享·笔记·其他
Aczone282 小时前
硬件(六)arm指令
开发语言·汇编·arm开发·嵌入式硬件·算法
luckys.one7 小时前
第9篇:Freqtrade量化交易之config.json 基础入门与初始化
javascript·数据库·python·mysql·算法·json·区块链
~|Bernard|8 小时前
在 PyCharm 里怎么“点鼠标”完成指令同样的运行操作
算法·conda
战术摸鱼大师8 小时前
电机控制(四)-级联PID控制器与参数整定(MATLAB&Simulink)
算法·matlab·运动控制·电机控制