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;
};
构造函数
- 对于顶点表进行初始化,所有的前驱数量置0,定点名称直接标记下标号,指向第一条边为空。
- 输入边的起点和终点,设置一条边的,终点是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求拓扑路径
- 首先,把所有前驱是0的顶点入栈,没有前驱结点可以直接入栈等待输出以及后续操作。
- 对于栈顶顶点,出栈,并且输出这个顶点的结点值,循环以该顶点开始的边表,找到后续的顶点并且前驱数量-1。
- 在栈不为空的条件下,循环进行第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;
}
}
}
注:在入栈操作的时候利用了反向的压栈,因为有部分的题目要求在相同的条件下,尽可能地先输出结点值小的点,由于栈是先入后出的,所以反向压栈。