Algorithm第四版算法 C++实现(十九)——Prim算法(求最小生成树)

Prim算法的原理是将某点与其他点最短的链接建立起来,遍历完v-1个点之后自然就可以生成一颗权重最小的树。

静态prim算法

class prim
{
private:
	std::vector<edge> pq;
	bool *marked;	//标记是否访问
	std::vector<edge> mst;	//最终路径
	void visit(EWgraph g, int v)
	{
		marked[v] = true;
		for (edge e : g.iterator(v))
		{
			if (!marked[e.other(v)])
			{
				pq.push_back(e);
			}
		}
		std::sort(pq.begin(), pq.end(),ewcmp);
	}
public:
	prim(EWgraph g)
	{
		marked = new bool[g.numv];
		std::fill(marked, marked + g.numv(), 0);
		visit(g, 0);
		while (!pq.empty())
		{
			edge e = *pq.end();
			pq.pop_back();
			int v = e.either();
			int w = e.other(v);
			if (marked[v] && marked[w])
			{
				continue;
			}
			mst.push_back(e);
			if (!marked[v])
				visit(g, v);
			if (!marked[w])
				visit(g, w);
		}
	}
	std::vector<edge> edges()
	{
		return mst;
	}
};

动态prim算法

动态prim算法通过不断更新一个到达某点的数组并从中选出权重最小的一条边并将其中一点继续遍历来实现生成最小树

class prim
{
private:
	bool *marked;	//标记是否访问
	double *dist_to;	//标记路径长短
	std::vector<edge> edge_to;
	std::vector<edge> temp;
	int min;
	std::vector<edge> mst;	//最终路径
	void visit(EWgraph g, int v)
	{
		marked[v] = true;
		edge tempe(0, v, inf);
		edge_to[v] = tempe;
		for (edge e : g.iterator(v))
		{
			int w = e.other(v);
			if (marked[w])
			{
				continue;
			}
			if (e.weight() < dist_to[w])
			{
				edge_to[w] = e;
				dist_to[w] = e.weight();
			}
		}
		temp = edge_to;
		std::sort(temp.begin(), temp.end(), ewcmp);
		mst.push_back(temp[0]);
		min = temp[0].either();
		if(marked[min])
			min = temp[0].other(temp[0].either());
		/*
		marked[v] = true;
		for (edge e : g.iterator(v))
		{
			if (!marked[e.other(v)])
			{
				pq.push_back(e);
			}
		}
		std::sort(pq.begin(), pq.end(),ewcmp);
		*/
	}
public:
	prim(EWgraph g)
	{
		marked = new bool[g.numv()];
		std::fill(marked, marked + g.numv(), 0);
		dist_to = new double[g.numv()];
		std::fill(dist_to, dist_to + g.numv(), inf);
		edge_to.resize(g.numv());
		edge e(0, 0, 0);
		edge_to[0] = e;
		min = 0;
		for(int i=0;i<g.numv()-1;i++)
		{
			visit(g,min);
		}
		/*
		marked = new bool[g.numv];
		std::fill(marked, marked + g.numv(), 0);
		visit(g, 0);
		while (!pq.empty())
		{
			edge e = *pq.end();
			pq.pop_back();
			int v = e.either();
			int w = e.other(v);
			if (marked[v] && marked[w])
			{
				continue;
			}
			mst.push_back(e);
			if (!marked[v])
				visit(g, v);
			if (!marked[w])
				visit(g, w);
		}
		*/
	}
	std::vector<edge> edges()
	{
		return mst;
	}
};

ewcmp函数见上期,今天不多说了,lei了

运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值