最小生成树代码实现(一)——克鲁斯卡尔算法

本文介绍最小生成树的克鲁斯卡尔算法,重点在于C++代码实现。文章首先介绍了最小生成树的基本概念,然后详细讲解了克鲁斯卡尔算法的步骤,包括边的排序和使用并查集判断环。最后给出了Kruskal函数的核心代码,并建议初学者通过观看推荐的视频辅助学习。
摘要由CSDN通过智能技术生成

打算出两个系列,对最小生成树的原理和代码实现进行讲解。由于最小生成树的代码在很多教科书和网站都有讲解,所以这里的重点是代码的实现。本文的代码语言为C++,《大话数据结构》中用的是C语言,各位可以参考下。本文的主要实现是基于B站的up主@WAY_zhong的动画,链接为:最小生成树(Kruskal(克鲁斯卡尔)和Prim(普里姆))算法动画演示述

十分推荐大家去看,该视频生动地描述了最小生成树的原理,本文的代码就是基于该视频的。

代码的基本思想

生成树的基本概念

最小生成树代码,包括普利姆算法和克鲁斯卡尔算法(都基于贪婪算法)

  1. 最小生成树是树,所以不能形成环
  2. 需要连接所有顶点
  3. N个顶点会有N-1条边
  4. 在所有生成树中,最小生成树要求权值和最小

克鲁斯卡尔算法

克鲁斯卡尔算法(基本思想:直接选择那些权值最小的边,判断这些边是否可以构成树/如果可以,添加进结果集,如果不可以就舍弃

步骤:

  1. 将所有边放入一个列表中,并按权值从小到大开始排序
  2. 从列表中从头开始取出一条边,将图中离散的点进行连接,如果没有构成环就添加,构成环就舍弃

代码实现

先给出整体代码,再对代码各部分模块进行分析

#include<vector>
#include<iostream>
#include<algorithm>
#define max INT_MAX
using namespace std;

//定义边集数组结构(该数组就是第1步中所说的列表)
struct EdgWeigt
{
   
	int begin;
	int end;
	int weight;
};


//并查集的find函数,用于判断是否存在环
class Djset
{
   
	vector<int> parent;
	vector<int> rank;
	int N;
	
public:
	Djset(){
   }
	Djset(vector<int> &parent, vector<int> &rank, int N):parent(parent), rank(rank), N(N)
	{
   
		
	}
	int find(int x)
	{
   
		int x_root = x;
		while (parent[x_root] != -1)
		{
   
			x_root = parent[x_root];
		}
		return x_root;
	}

	void merge(int x, int y)
	{
   
		int x_root = find(x);
		int y_root = find(y);
		if (x_root == y_root) return;
		else {
   
			if (rank[x_root] > rank[y_root])
			{
   
				parent[y_root] = x_root;
                
			}
			else if (rank[y_root] > rank[x_root])
			{
   
				parent[x_root] = y_root;
               
			}
			else if (rank[y_root] == rank[x_root])
			{
   
				parent[x_root] = y_root;
				rank[y_root] ++;
			}
		}
	}
};


void Kruskal(vector<vector<int>> &graph)
{
   
	//在这里,输入的图为无向图,所以权值邻接矩阵是对称的
	vector<EdgWeigt> edgeArr;//边集数组

	//初始化边集数组
	
	for (int i = 0; i < graph.size(); ++i)
	{
   
		for (int j = i+1; j < graph[i].size(); ++j)
		{
   
			EdgWeigt edge;
			edge.begin = i;
			edge.end = j;
			edge.weight = graph[i][j]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值