【图(下)】拓扑排序

1、举例说明:计算机专业排课

在这里插入图片描从述
说明:学C1,C2是不需要提前学别的课程的,学C3则需要提前学C1,C2。

把课程列表转换为图,其中顶点代表课程,则从V到W有一条边代表:V是W的预修课程

2、拓扑排序

  • 拓扑序:如果图中从V到W有一条有向路径,则V一定排在W之前。满足此条件的顶点序列称为一个拓扑序
  • 获得一个拓扑序的过程就是拓扑排序
  • AOV如果有合理的拓扑序,则必定是有向无环图(Directed Acyclic Graph, DAG)
    在这里插入图片描述

3、算法

在这里插入图片描述

void TopSort()
{
	for (cnt = 0; cnt < |V| ; cnt++)
	{
		V = 未输出的入度为0的顶点;// O(|V|)
		if (这样的V不存在)//外循环没结束已经找不到入度为0的顶点了,有环
		{
			Error(“图中有回路”);
			break;
		}
		输出V,或者记录V的输出序号;
		for (V 的每个邻接点W)
			Indegree[W]––;//相当于去掉从V到W的边
	}
}

在TopSort函数中,如果外循环还没结束,就已经找不到“未输出的入度为0的顶点”,则说明图中必定存在回路。

时间复杂度:T = O( |V|2 )

4、聪明的算法

随时将入度变为0的顶点放到一个容器里

void TopSort()
{
	for (图中每个顶点V)
		if (Indegree[V] == 0)
			Enqueue(V, Q);
	while (!IsEmpty(Q))
	{
		V = Dequeue(Q);
		输出V,或者记录V的输出序号; cnt++;//计数器增加
		for (V 的每个邻接点W)//将V放入容器,V发出的边断开,V的邻接点入度减1
			if (––Indegree[W] == 0)
				Enqueue(W, Q);
	}
	if (cnt != |V| )
		Error(“图中有回路”);
}

随时将入度为0的节点放入容器中,每次从容器中取出元素,保证都是入度为0。

时间复杂度:每个点被访问一遍,每条边访问一遍
T = O( |V| + |E| )

此算法可以用来检测有向图是否DAG(有向无环图Directed Acyclic Graph)

5、关键路径问题

  • AOE (Activity On Edge) 网络
    一般用于安排项目的工序
    在这里插入图片描述
    每条边代表一个工序或者一个活动
    边表示活动,顶点表示到达这个顶点时,活动结束了。

顶点的上面部分表示这项工作最早在什么时间完成,下面的表示这项工作最晚什么时间开始。
在这里插入图片描述
在这里插入图片描述
机动时间:不用那么赶工期,以顶点0到顶点2为例,最早第0天开始工作,最晚第六天完成,而完成这项工作只需要4天时间,就有2天的机动时间。
关键路径:由绝对不允许延误的活动组成的路径

猜你喜欢

转载自blog.csdn.net/happyjacob/article/details/84035638