数据结构(C++)AOV网与拓扑排序

AOV网:在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,称这样的有向图为顶点表示活动的网,简称AOV网。

AOV网特点:
1.AOV网中的弧表示活动之间存在的某种制约关系。
2.AOV网中不能出现回路。

拓扑序列:
设G = (V,E)是一个具有n个顶点的有向图,V中的顶点序列v1, v2, …, vn称为一个拓扑序列,当且仅当满足下列条件:若从顶点vi到vj有一条路径,则在顶点的拓扑序列中顶点vi必在顶点vj之前。

**拓扑排序:**对一个有向图构造拓扑序列的过程称为拓扑排序 。

拓扑序列使得AOV网中所有应存在的前驱和后继关系都能得到满足。

基本思想:

⑴ 从AOV网中选择一个没有前驱的顶点并且输出;
⑵ 从AOV网中删去该顶点,并且删去所有以该顶点为尾的弧;
⑶ 重复上述两步,直到全部顶点都被输出,或AOV网中不存在没有前驱的顶点。

基本构造

根据图的链式存储结构建图,分别建立一条主链表,用来存储全部的顶点,每个顶点的数据分别有:
1、该顶点的前驱数量。
2、该顶点的顶点名称。
3、该顶点所指向的下一条的结构化边。

建立边表,其中边表的组成有该边的下一个顶点,还有在顶点表里原顶点所连接的其他顶点边。

struct ArcNode // 边
{
	int adjvex;
	ArcNode* next;
};
struct VertexNode // 顶点
{
	int pre;
	int vertex;
	ArcNode* firstedge;
};

构造函数

  1. 对于顶点表进行初始化,所有的前驱数量置0,定点名称直接标记下标号,指向第一条边为空。
  2. 输入边的起点和终点,设置一条边的,终点是b,使用头插法插入到a顶点的后方,并且b顶点的前驱数加1。
ALGraph(int n, int e)
{
	arcNum = e;
	vertexNum = n;
	ArcNode* s;
	for (int i = 1; i <= vertexNum; ++i)
	{
		adjlist[i].pre = 0;
		adjlist[i].vertex = i;
		adjlist[i].firstedge = NULL;
	}
	for (int i = 1; i <= arcNum; ++i)
	{
		int a, b;
		cin >> a >> b;
		s = new ArcNode;
		s->adjvex = b;
		s->next = adjlist[a].firstedge;
		adjlist[a].firstedge = s;
		adjlist[b].pre++;
	}
}

AOV求拓扑路径

  1. 首先,把所有前驱是0的顶点入栈,没有前驱结点可以直接入栈等待输出以及后续操作。
  2. 对于栈顶顶点,出栈,并且输出这个顶点的结点值,循环以该顶点开始的边表,找到后续的顶点并且前驱数量-1。
  3. 在栈不为空的条件下,循环进行第2步,直到栈为空,所有的顶点都遍历结束。
void AOV()
{
	stack<int>s;
	int j, k;
	ArcNode* p;
	for (int i = vertexNum; i >= 1; i--)
	{
		if (adjlist[i].pre == 0)
		{
			s.push(i);
		}
	}
	while (!s.empty())
	{
		j = s.top();
		s.pop();
		cout << "v" << adjlist[j].vertex << " ";
		p = adjlist[j].firstedge;
		while (p != NULL)
		{
			k = p->adjvex;
			adjlist[k].pre--;
			if (adjlist[k].pre == 0)
			{
				s.push(k);
			}
			p = p->next;
		}
	}
}

注:在入栈操作的时候利用了反向的压栈,因为有部分的题目要求在相同的条件下,尽可能地先输出结点值小的点,由于栈是先入后出的,所以反向压栈。

你可能感兴趣的:(数据结构,数据结构,AOV,拓扑,图论算法)