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了

运行结果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值