拓扑排序指的是将有向无环(又称“DAG”图)中的顶点按照图中指定的先后顺序进行排序。
图 1 有向无环图
例如,图 1 中的两个图都是有向无环图,都可以使用拓扑排序对图中的顶点进行排序,两个图形的区别是:左图中的 V2 和 V3 之间没有明确的前后顺序;而右图中任意两个顶点之间都有前后顺序。
所以,左图中顶点之间的关系被称为“偏序”关系;右图中顶点之间的关系被称为”全序“关系。
在有向无环图中,弧的方向代表着顶点之间的先后次序,例如从 V1 指向 V2 的弧表示在进行排序时 V1 在前, V2 在后。
全序是偏序的一种特殊情况。对于任意一个有向无环图来说,通过拓扑排序得到的序列首先一定是偏序,如果任意两个顶点都具有前后顺序,那么此序列是全序。
拓扑排序的方法
对有向无环图进行拓扑排序,只需要遵循两个原则:
在图中选择一个没有前驱的顶点 V;
从图中删除顶点 V 和所有以该顶点为尾的弧。
例如,在对图 1 中的左图进行拓扑排序时的步骤如图 2 所示:
图 2 拓扑排序
有向无环图如果顶点本身具有某种实际意义,例如用有向无环图表示大学期间所学习的全部课程,每个顶点都表示一门课程,有向边表示课程学习的先后次序,例如要先学《程序设计基础》和《离散数学》,然后才能学习《数据结构》。所以用来表示某种活动间的优先关系的有向图简称为“AOV网”。
进行拓扑排序时,首先找到没有前驱的顶点 V1,如图 2(1)所示;在删除顶点 V1 及以 V1 作为起点的弧后,继续查找没有前驱的顶点,此时, V2 和 V3 都符合条件,可以随机选择一个,例如图 2(2) 所示,选择 V2 ,然后继续重复以上的操作,直至最后找不到没有前驱的顶点。
所以,针对图 2 来说,拓扑排序最后得到的序列有两种:
V1 -> V2 -> V3 -> V4
V1 -> V3 -> V2 -> V4
如果顶点之间只是具有偏序关系,那么拓扑排序的结果肯定不唯一;如果顶点之间是全序关系,那么拓扑排序得到的序列唯一。
拓扑排序的C语言实现
在编写程序解决拓扑排序的问题时,大致思路为:首先通过#include
#include
#define MAX_VERTEX_NUM 20//最大顶点个数
#define VertexType int//顶点数据的类型
typedef enum{false,true} bool;
typedef struct ArcNode{
int adjvex;//邻接点在
例如使用上述完整代码解决下图的有向无环图时,拓扑排序的结果为:
运行效果:
6,8
1
2
3
4
5
6
1,2
1,4
1,3
3,2
3,5
4,5
6,4
6,5
6 1 4 3 2 5