Algorithm第四版算法 C++实现(十六)——拓扑排序(调度问题)、环和无环有向图

在现实中,我们经常会遇到如图所示问题
在这里插入图片描述
这张图指明了想要完成指定的任务所需完成的前置任务。这种问题叫做调度问题。我们需要得知如何安排才能使得所有任务顺利完成。这就叫做优先级限制下的调度问腿
拓扑排序:给定一副有向图,将所有顶点排序,使得所有有向边均从排在前面的元素指向排在后面的元素
在这里插入图片描述
要解决调度问题,首先我们需要确定图中有没有。很明显,当有向图种存在环时,调度问题是无解的

有向环检测

//寻找有向环
class directedcycle
{
public:
	directedcycle(digraph g)
	{
		marked = new bool(g.numv());
		edgeto = new int(g.numv());
		onstack = new bool(g.numv());
		for (unsigned int v = 0; v < g.numv(); v++)
		{
			if (!marked[v])
				dfs(g,v);
		}
	}
	bool has_cycle()
	{
		return !cycle.empty();
	}
private:
	bool *marked;
	int *edgeto;
	bool *onstack;
	std::vector<int> cycle;
	void dfs(digraph g, int v)
	{
		onstack[v] = true;
		marked[v] = true;
		for (auto w : g.iterator(v))
		{
			if (has_cycle())
				return;
			else if (!marked[v])
			{
				edgeto[w] = v;
				dfs(g, w);
			}
			else if (onstack)
			{
				for (int i = v; i != w; i = edgeto[i])
				{
					cycle.push_back(i);
				}
				cycle.push_back(w);
				cycle.push_back(v);
			}
		}
		onstack[v] = false;		//如果走到这一步说明从v出发搜索完成所有的子节点,需要回退,可以将v设置为不在遍历中了
	}
};

这个算法的原理其实挺简单的,主要思想还是深度优先算法,只不过我们会把走过的路径记住,并在每次调用dfs方法是查看我们是否走到正在遍历中的点

有向图中基于深度优先搜索的顶点排序

我们其实可以直接使用深度优先搜索来对有向无环图进行排序。

//基于深度优先搜索的顶点排序
class DFO
{
private:
	bool *marked;
	std::vector<int> pre;
	std::vector<int> post;
	std::vector<int> revers_post;
	void dfs(digraph g, int v)
	{
		pre.push_back(v);
		marked[v] = true;
		for (int i=0;i<g.iterator(v).size();i++)
		{
			int w = g.iterator(v)[i];
			if (!marked[w])
			{
				dfs(g, w);
			}
			//printf("?");
		}
		//printf("#%d", v);
		post.push_back(v);
		revers_post.push_back(v);
	}
public:
	DFO(digraph g)
	{
		marked = new bool[g.numv()];
		std::fill(marked, marked + g.numv(), 0);
		for (unsigned int v = 0; v < g.numv(); v++)
		{
			if (!marked[v])
			{
				dfs(g, v);
			}
				
		}
	}
	std::vector<int> pre_order()
	{
		return pre;
	}
	std::vector<int> post_order()
	{
		return post;
	}
	std::vector<int> rp_order()
	{
		std::reverse(revers_post.begin(), revers_post.end());
		return revers_post;
	}
};

拓扑排序

std::vector<int> topo(digraph g)
{
	std::vector<int> order;
	directedcycle cyclefinder(g);
	if (!cyclefinder.has_cycle())
	{
		DFO dfs(g);
		order = dfs.rp_order();
	}
	return order;
}

运行结果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值