数据结构(C语言实现)-图(4)(有向无环图:拓扑排序与关键路径)

有向无环图(DAG图)就是没有环路的有向图,即以任意一个顶点为起点出发,走任意一条路径也不能回到起点。
有向无环图常用来描述一项工程的进行过程,这个工程分为一系列子工程,而一些子工程的开始必须以某些子工程的结束为条件。
对应于一个工程或系统,人们常常关心两个问题:(1)工程能否顺利进行,这是拓扑排序问题。(2)工程完成所需要的最短时间,这是关键路径问题。

文章目录

  • 拓扑排序
  • 关键路径

拓扑排序

由某个集合上的一个偏序,得到该集合上的一个全序

偏序:R是集合上的二元关系,R满足(1)自反性(2)反对称性(3)传递性
全序:对于集合上的二元关系,满足(1)完全性(2)反对称性(3)传递性(完全性包含了自反性)
直观理解:偏序是集合中只有部分元素间可比较(先后、大小等),全序是集合中任意元素间都可比较。

顶点表示活动,弧表示活动间先后关系的有向图称为AOV网(顶点表示活动的网)。
拓扑排序步骤:重复以下步骤:(1)在有向图中选取一个没有前驱的顶点,输出之。(2)图中删除该点和所有与之相连的弧。直至图中不再有顶点(活动)存在。

我们用邻接表作为图的存储结构,稍有的一点改变是在顶点节点增加一个数据域,用来存储顶点入度。同时要使用一个栈来存储入度为零的顶点。邻接表和栈的实现用前面的代码。以下是拓扑排序代码实现:

int TopologicalSort(ALgraph *G)
{
	SqStack s;
	InitStack(s);
	int indegree[G.vexnum-1]=0;      //设置辅助数组,实时记录每个顶点的入度
	FindInDegree(G,indegree);        //辅助数组初始化,统计初始图中每个顶点的入度
	for(int i = 0;i<G.vexnum-1;i++)
		if(!indegree[i]) Push(s,i);  //入度为0的顶点的序号入栈
	
	int count = 0;                   //设一个计数变量,用来判断该图是否有环
	while(s.top != s.base)           //栈不为空
	{
		int i;
		Pop(s,i);
		printf("按拓扑排序顺序输出顶点,接下来的顶点是:%c",G.vertices[i].data);
		count++;                     //每输出一个顶点,计数加一
		for(ArcNode p = G.vertices[i].firstarc; p; p=p->nextarc)//与第i个顶点相连的所有弧
		{
			int j = p->adjvex;       //弧指向的顶点
			if(!(--indegree[j]))     //入度减一
				Push(s,j);           //若入度为0,入栈
		}
	}

	if(count<G.vexnum)
		return ERROR;  //说明该有向图有环       
	else
		return OK;
}

void FindInDegree(ALGraph G,int* indegree)
{
	for(int i = 0;i<G.vexnum-1;i++)
	{
		for(ArcNode p = G.vertices[i].firstarc; p; p=p->nextarc)//与第i个顶点相连的所有弧
		{
			int j = p->adjvex;       //弧指向的顶点
			indegree[j]++;
		}
	}
}

关键路径

弧表示活动,权值表示活动持续时间,顶点表示时间节点的有向图称为AOE网(边表示活动的网
在AOE网中,有些活动可以并行的进行,所以完成工程的最短时间是由开始点到结束点的最长路径长度(路径上各活动持续时间之和),这条路径就叫关键路径。

你可能感兴趣的:(数据结构)