细讲拓朴排序

拓扑排序是对有向无环图(DAG)的顶点进行排序,使得对任何边(u,v),u总是在v之前。文章介绍了拓扑排序的算法思想,包括选择入度为0的顶点输出,删除相关边,重复此过程,以及如何判断有向图是否存在环。拓扑排序在工程进度安排等方面有实际应用,且其序列不唯一。文章提供了一个简单的算法实现,并通过家谱树的例子进行解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是拓朴排序

拓扑排序算法,只适用于 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 的点。

我们结合下图详细讲解:

 

 

简单&高效&实用的算法。上述实现方法复杂度O(V+E)

例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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值