拓扑排序及关键路径


const int MaxVertexNum = 50;

struct edgenode
{
	int adjvex;  //邻接点
	int weight;
	edgenode *next;  //指向下一个边结点的链域
};

typedef edgenode *adjlist[MaxVertexNum];

/*
把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网
(Activity On Vertex network ),简称AOV网。
在AOV网中,若不存在回路,则所有活动可排列成一个线性序列,使得每个活动的所
有前驱活动都排在该活动的前面,我们把此序列叫做拓扑序列(Topological order),
由AOV网构造拓扑序列的过程叫做拓扑排序(Topological sort )。
AOV网的拓扑序列不是唯一的,满足上述定义的任一线性序列都称做它的拓扑序列。
*/

/*
由AOV网构造出拓扑序列的实际意义是:如果按照拓扑序列中的顶点次序,在开始每一项活动时,
能够保证它的所有前驱活动都已完成,从而使整个工程顺序进行,不会出现冲突的情况。
由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
	(1)选择一个入度为0的顶点并输出之;
	(2)从网中删除此顶点及所有出边。
循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,
否则输出的顶点序列就是一种拓扑序列。
*/

/*拓扑排序算法*/
#ifndef TOPOSORT

void Toposort(adjlist GL, int n)
	//对用邻接表GL表示的有向图进行拓扑排序
{
	int i,j,k,top,m = 0;  //m用来统计拓扑序列中的顶点数
	edgenode *p;
	//定义存储图中每个顶点入度的一维整型数组d
	int *d = new int[n];
	memset(d,0,sizeof(d));  //初始化数组d中的每个元素值为0
	//利用数组d中的对应元素统计出每个顶点的入度
	for (i = 0; i < n; i++)
	{
		p = GL[i];
		while (p != NULL)
		{
			j = p->adjvex;
			d[j]++;
			p = p->next;
		}
	}
	//初始化用于链接入度为0的元素的栈的栈顶指针top为-1
	top = -1;
	//建立初始化栈
	for(i = 0; i < n; i++)
	{
		if(d[i] == 0)
		{
			d[i] = top;
			top = i;
		}
	}
	//每循环一次删除一个顶点及所有出边
	while(top != -1)
	{
		j = top;   //j的值为一个入度为0的顶点序号
		top = d[top];  //删除栈顶元素
		cout<adjvex;   //Vk是Vj的一个邻接点
			d[k]--;   //Vk的入度减1
			if (d[k] == 0)   //把入度为0的元素进栈
			{
				d[k] = top;
				top = k;
			}
			p = p->next;   //p指向Vj邻接点表的下一个结点
		}
	}
	cout<adjvex;
			d[j]++;
			p = p->next;
		}
	}
	//初始化用于链接入度为0的元素的栈的栈顶指针top为-1
	top = -1;
	//建立初始化栈
	for(i = 0; i < n; i++)
	{
		if(d[i] == 0)
		{
			d[i] = top;
			top = i;
		}
	}
	//每循环一次删除一个顶点及所有出边
	while(top != -1)
	{
		j = top;   //j的值为一个入度为0的顶点序号
		top = d[top];  //删除栈顶元素
		v[m] = j;
		m++;   //输出的顶点加1
		p = GL[j];  //p指向vj邻接点表的第一个结点
		while (p != NULL)
		{
			k = p->adjvex;   //Vk是Vj的一个邻接点
			d[k]--;   //Vk的入度减1
			if (d[k] == 0)   //把入度为0的元素进栈
			{
				d[k] = top;
				top = k;
			}
			p = p->next;   //p指向Vj邻接点表的下一个结点
		}
	}
	cout<adjvex;   //k为邻接点
			if(ve[k] < ve[j] + p->weight)   //较大值
				ve[k] = ve[j] + p->weight;
			p = p->next;
		}
	}
	//把每个事件的最迟发生时间都置为ve[n-1],以作为它们的初值
	for(i = 0; i < n; i++)
		vl[i] = ve[n-1];
	//求出每个事件的最迟发生时间
	for (i = n-1; i >= 0; i--)
	{
		j = v[i];
		p = GL[j];
		while(p != NULL)
		{
			k = p->adjvex;  //k为邻接点
			if(vl[j] > vl[k] - p->weight)  //较小值
				vl[j] = vl[k] - p->weight;  
			p = p->next;
		}
	}
	//输出AOE网中每一个活动的最早开始时间,最迟开始时间,
	//以及开始时间余量
	for (i = 0; i < n; i++)
	{
		p = GL[i];   //把vi邻接点表的表头指针赋给p
		while(p != NULL)
		{
			j = p->adjvex;  //Vj是Vi的一个后继事件
			cout<<"<"<";   //输出有向边,用它表示该边上的活动ak
			cout<weight<<",";   //输出ak的最迟开始时间
			cout<weight - ve[i]<为关键路径上的一条边
			p = p->next;
		}
	}
}

#endif



你可能感兴趣的:(数据结构应用实例)