C++Kruskal算法求最小生成树

C++Kruskal算法求最小生成树

刚开始写Kruskal算法时,苦于无法解决如何判断并入的最短路径是否形成回路的问题,卡了很久。后来学习了并查集的概念,才明白并查集是Kruskal算法的关键。
并查集用于判断元素是否处于同一集合中,在Kruskal算法中可用于判断是否存在环。
并查集可定义为一个一维数组parent,初始化时令parent[i]=i;即此时自身为一个单独的集合。
查询:
int Find(int x,int* visited) {
		int root = x;
		while (root != visited[root]) {
			root = visited[root];
		}
		return root;
	}
合并:
void merge(int begin,int end,int* parent){
	int i=Find(begin,parent);
	int j=Find(end,parent);
	if(i!=j){
		parent[j]=i;
	}
}

用了并查集后就可以写Kruskal算法了,以下是Kruskal.h:

#pragma once
#include<iostream>
#include<vector>
#include"MGraph.h"

class Kruskal {
public:
	Kruskal() = default;
	~Kruskal() = default;
	void KruskalAlgorithm(MGraph M) {
		GetVEdges(M);
		MySort();
		for (int i = 0;i < M.NumVertexes;++i) visited.push_back(i);
		for (int i = 0;i < M.NumEdges;++i) {
			int Ver1 = Find(VEdges[i].begin);
			int Ver2 = Find(VEdges[i].end);
			if (Ver1 != Ver2) {
				visited[Ver2] = Ver1;
				lowest.push_back(VEdges[i].weight);
			}
		}
	}
	void Showlowest() {
		int sum = 0;
		for (auto x : lowest) {
			cout << x << " ";
			sum += x;
		}
		cout << endl;
		cout << "Lowest:" << sum << endl;
	}
private:
	void GetVEdges(MGraph M) {
		for (int i = 0;i < M.NumVertexes;++i) {
			for (int j = 0;j < M.NumVertexes;++j) {
				if (i != j && M.arc[i][j] != Infinity) {
					M.arc[j][i] = Infinity;
					Edges edge;
					edge.begin = i;
					edge.end = j;
					edge.weight = M.arc[i][j];
					this->VEdges.push_back(edge);
				}
			}
		}
	}//将有向图转换成无向图
	void MySort() {
		for (unsigned int i = 0;i < VEdges.size();++i) {
			for (unsigned int j = i + 1;j < VEdges.size();++j) {
				if (VEdges[j].weight < VEdges[i].weight) {
					Edges temp = VEdges[i];
					VEdges[i] = VEdges[j];
					VEdges[j] = temp;
				}
			}
		}
	}//按权值将边排序
	int Find(int x) {
		int root = x;
		while (root != visited[root]) {
			root = visited[root];
		}
		return root;
	}

private:
	struct Edges {
		int begin;
		int end;
		int weight;
	};
private:
	vector<Edges>VEdges;
	vector<int>visited;
	vector<int>lowest;
};
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值