Algorithm第四版算法 C++实现(十八)——加权无向图的构造及kruskal算法(求最小生成树)

带权边的构造

/*带权图的边*/
class edge
{
private:
	int v;
	int w;
	double wei;
public:
	edge(int v, int w, double weight)
	{
		this->v = v;
		this->w = w;
		this->wei = weight;
	}
	double weight()
	{
		return wei;
	}
	int either()
	{
		return v;
	}
	int other(int ver)
	{
		if (ver == v)
			return w;
		else
			return v;
	}
	int cmpt(edge that)
	{
		if (this->weight() < that.weight())
			return -1;
		else if (this->weight() == that.weight())
			return 0;
		else
			return 1;
	}
	std::string to_string()
	{
		char str[20];
		sprintf_s(str,20 ,"%d-%d %.2f\n", v, w, wei);
		std::string s(str);
		return s;
	}
};

带权图的构造

/*带权图*/
class EWgraph	
{
private:
	int v;
	int e;
	std::vector<std::vector<edge>> adj;
public:
	EWgraph(int v)
	{
		this->v = v;
		this->e = 0;
		adj.resize(v);
	}
	int numv()
	{
		return v;
	}
	int nume()
	{
		return e;
	}
	void add_edge(edge e)
	{
		int v = e.either();
		int w = e.other(v);
		adj[v].push_back(e);
		adj[w].push_back(e);
		this->e++;
	}
	std::vector<edge> iterator(int v)
	{
		return adj[v];
	}
	std::vector<edge> edges()	//返回所有边
	{
		std::vector<edge> v;
		for (int i = 0; i < this->v; i++)
		{
			for (auto e : adj[i])
			{
				
				if(e.other(i) > i)
				{
					v.push_back(e);
				}
			}
		}
		return v;
	}
};


其实我从不太习惯用这种方式来构造带权图,我更喜欢使用二维数组构建一个邻接矩阵来表示带权图。虽然这种方法可能回浪费大量的空间,但是在速度上可能会比大量的使用类更快。当然我们C/C++程序员可能天生不如JAVA程序员那么喜欢面向对象

kruskal

基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路,即保证属于同一连通分支的两点之间的路径不会被选择
在这里插入图片描述

bool ewcmp(edge a, edge b)
{
	return a.cmpt(b) < 0;
}

std::vector<edge> kruskal(EWgraph g)
{
	std::vector<edge> mst;
	std::vector<edge> all = g.edges();
	union_find color(g.numv());
	std::sort(all.begin(), all.end(), ewcmp);
	for (auto i : all)
	{
		int v = i.either();
		int w = i.other(v);
		if (color.connected(v, w))
		{
			
			continue;
		}
		color.uf(v, w);
		mst.push_back(i);
		if (mst.size() >= g.numv()- 1)
			break;
	}
	return mst;
}

用到了第一章中出现的union-find算法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值