什么是拓朴排序
拓扑排序算法,只适用于
AOV
网(有向无环图)。
把AOV
网中的所有活动排成一个序列, 使得每个活动的所有前驱活动
都排在该活动的前面,这个过程称为“拓扑排序”,所得到的活动序列称
为“拓扑序列”。
一个
AOV
网的拓扑序列是不唯一的,例如下面的这张图,它的拓扑序
列可以是:
ABCDE
,也可以是
ACBDE
,或是
ADBCE
。在下图所示的
AOV
网中,工程
B
和工程
C
显然可以同时进行,先后无所谓;但工程
E
却要等工
程
B
、
C
、
D
都完成以后才能进行。

构造拓扑序列可以帮助我们合理安排一个工程的进度,由AOV
网构
造拓扑序列具有很高的实际应用价值。
算法思想
构造拓扑序列的拓扑排序算法思想很简单:
(1)
选择一个入度为
0
的顶点并输出。
(2)
然后从
AOV
网中删除此顶点及以此顶点为起点的所有
关联边。
(3)
重复上述两步,直到不存在入度为
0
的顶点为止。
(4)
若输出的顶点数小于
AOV
网中的顶点数,则输出“有
回路信息”,否则输出的顶点序列就是一种拓扑序列。
从第四步可以看出,拓扑排序可以用来判断一个有向
图是否有环。只有有向无环图才存在拓扑序列。
算法实现:
(a)
数据结构:
indgr[i]:
顶点
i
的入度
;
stack[ ]:
栈
(b)
初始化
:top=0 (
栈顶指针置零
)
(c)
将初始状态所有入度为
0
的顶点压栈
(d) i=0 (
计数器
)
(e) while
栈非空
(top>0)
i.
栈顶的顶点
v
出栈;
top-1;
输出
v
;
i++
;
ii. for v
的每一个后继顶点
u
1. indgr[u]--; u
的入度减
1
2. if
(
u
的入度变为
0
) 顶点
u
入栈
(f)
算法结束
这个程序采用栈来找出入度为
0
的点,栈里的顶点,都是
入度为
0
的点。
我们结合下图详细讲解:
简单&高效&实用的算法。上述实现方法复杂度
。
例1
.
家谱树
【问题描述】
有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关
系。
给出每个人的孩子的信息。
输出一个序列,使得每个人的后辈都比那个人后列出。
【输入格式】
第
1
行一个整数
N
(
1<=N<=100
),表示家族的人数。
接下来
N
行,第
i
行描述第
i
个人的儿子。
每行最后是
0
表示描述完毕。
【输出格式】
输出一个序列,使得每个人的后辈都比那个人后列出。
如果有多解输出任意一解。
【输入样例】
5
0
4 5 1 0
1 0
5 3 0
3 0
【输出样例】
2 4 5 3 1
代码实现
#include<cstdio>
#include<iostream>
using namespace std;
int a[101][101],c[101],r[101],ans[101];
int i,j,tot,temp,num,n,m;
int main()
{
cin >> n;
for (i = 1; i <= n; i++)
{
do
{
cin >> j;
if (j !=0 )
{
c[i]++;//c[i]用来存i的出度
a[i][c[i]] = j;
r[j]++;//r[j]用来存j的入度
}
} while (j != 0);
}
49
for (i = 1; i <= n; i++)
if (r[i] == 0)
ans[++tot] = i;//把图中所有入度为0的点入栈,栈用一维数组ans[]
表示
do
{
temp = ans[tot];
cout << temp << " ";
tot--;num++;//栈顶元素出栈输出
for (i = 1; i <= c[temp]; i++)
{
r[a[temp][i]]--;
if (r[a[temp][i]] == 0) //如果入度减1后变成0,则将这个后继点入
栈
ans[++tot] = a[temp][i];
}
}while (num != n);//如果输出的点的数目num等于n,说明算法结束
return 0;
}