定义:
拓扑排序:图中的点以线性方式进行排序。即若图中有一条边是u->v,则最后的排序结果中u总在v前面。类似于先序图的概念,必须先到达u点才能到达v点,则u>v。
适用条件:
并不是所有图都可以进行拓扑排序。这里有个重要的概念是离散数学中的偏序关系。
偏序的大意就是,如果图中的两个点有确定的大小关系,例如一条边上的两个点,或没有直接的联系,即两个点不相通,则就是偏序关系。不能存在互相矛盾的关系,比如环路,例如a->b,b->a,这种就不满足偏序关系。所以,只要一个图中不存在环路,不管图中的点连通与否,都满足偏序关系。而拓扑排序的条件就是这个图是有向无环图(DAG),有向是为了确定两个点的先后顺序,若无向,则关系都乱了。
唯一性:
图中顶点的拓扑关系并不像数字的大小关系那样简单,这里还有个重要的概念的离散数学中的全序关系。
全序关系在图中的大意就是,每个点都与其他所有点有着确定的先后顺序,那么这个图就满足全序关系。
这里用数组与图做对比来解释,任意两个不相等的数字之间有着确定的大小关系,所以数组就满足全序关系,这样排序后的结果就是惟一的。但是通常我们评价排序算法时,要考虑一个因素是稳定性,即相同数字的排序结果是否和出现的顺序一致。因为两个相同的数字的大小关系无法确定,不满足全序关系,那么他们在排序结果中的位置也就无法确定。
回到图中,如果DAG中的每个点都与其他所有点有确定的先后顺序,那么这个DAG的拓扑排序结果是惟一的,但是如果存在两个点不直接相连,即无法确定他们的拓扑关系,那么它们在拓扑结果中的位置就无法确定,拓扑结果就不唯一了。
基本思想:
拓扑排序有两种做法,一种是bfs的思路,一种是dfs的思路。本文介绍bfs方法,bfs是以入度为切入点,一个点的入度越小,则排在它前面的点就越少。基本思想是动态维护一个入度为0的顶点的队列。然后取一个点出发,依次将图中与该点相连
的边去掉,如果在过程中又出现了新的入度为0的顶点,则加入队列中,直到队列为空。如果此时图中没有边了,则
不存在环路,从而得到排序结果,这也说明bfs方法可以检测一个图是不是有向无环图。
数据结构:
算法中涉及到的数据结构有以下几种:
1、图的邻接矩阵,用来表示图。
2、保存排序结果的集合,一般用vector。
3、入度数组,用来保存每个点的入度。
4、队列,用来保存当前入度为0并且没有遍历到的点。
算法过程:
1、建图
2、遍历图中的所有点,统计每个点的入度,存到入度数组中
3、将入度为0的点入队
4、对当前队列中的点进行遍历,取出点并将它存到结果集中。再从该点出发,去掉图中以该点为起点的边,并且将边的终点的入度-1。同时判断终点的入度是否减为0,若为0,则入队。
5、重复4,直到队列为空。
c++代码:
#include<iostream>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;
vector<int> *edge;//边集
vector<int> res;//结果集
queue<int> q;
int in[101];//入度数组
int n,m,edges;//edges表示此时图中所剩的边数
int main()
{
int a,b;
cin>>n>>m;
edges=m;
edge=new vector<int>[n];
memset(in,0,sizeof(in));
for(int i=0;i<m;i++)
{
cin>>a>>b;
edge[a].push_back(b);
}
//统计入度
for(int i=0;i<n;i++)
for(int j=0;j<edge[i].size();j++)
in[edge[i][j]]++;
//将入度为0的点入队
for(int i=0;i<n;i++)
if(in[i]==0)
q.push(i);
int n;
while(!q.empty())
{
//取出一个点加入结果集
n=q.front();
q.pop();
res.push_back(n);
//遍历该点所引出的所有边
for(int i=0;i<edge[n].size();i++)
{
//edges--表示去掉了这条边
edges--;
//同时终点的入度-1
in[edge[n][i]]--;
if(in[edge[n][i]]==0)
q.push(edge[n][i]);
}
}
//若此时图中还存在边,则说明有环路。
if(edges!=0)
cout<<"Has circles!";
else
for(int i=0;i<res.size();i++)
cout<<res[i]<<" ";
return 0;
}
运行结果:
例子中的图有13个点,若是全序关系,则应该有(13-1)*13/2=78条边,显然这个图不满足全序关系,则排序结果不唯一。