拓扑排序-AOV网

博客皆个人学习过程中整理,如有问题,欢迎大家指正。
本文链接: https://blog.csdn.net/qq_42017331/article/details/101849457
简介:

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。如下图所示。
在这里插入图片描述

排序过程:

观察上图可以发现,每一个顶点都不会通过边指向自己的前驱顶点。

  1. 在有向图中,选取一个无前驱顶点且输出它
  2. 删除此顶点以及该顶点与其他顶点的连接
  3. 重复1,2步骤,直至不存在无前驱的顶点
算法实现:

为了不破坏图之间的关系,我们使用一个数组记录每个顶点的入度(入度表明顶点的前驱个数)。通过栈记录无前驱的顶点,倘若栈无记录则不存在无前驱的顶点。这里使用栈的原因是为了避免重复扫描记录入度的数组,因此使用队列同样可以达到目的。如果想记录拓扑排序的顶点序号,则需再增设一个数组。

实现步骤:
  1. 首先获取各顶点入度信息
  2. 若存在无前驱(入度=0)的顶点,则入栈
  3. 若栈不为空,则删除当前栈顶元素与其邻接点之间的连接,更新记录入度信息的数组
  4. 若存在入度为0的顶点,则入栈
代码示例:
#include<iostream>
#include<stack>
#include<queue>

using namespace std;
#define MAX_SIZE 100
int graph[MAX_SIZE][MAX_SIZE];
int degree[MAX_SIZE];
int seq[MAX_SIZE];

void init_arry(){
 	for(int i = 0; i < MAX_SIZE; i++){
  		for(int j = 0; j < MAX_SIZE; j++)
   			graph[i][j] = 0;
 	}  
}
void init_graph(int m){
 	for(int i = 0; i < m; i++){
  		int x, y;
  		cin >> x >> y;
  		graph[x][y] = 1;
 	}
}
void get_degree(int n){
 	for(int i = 1; i <= n; i++){
  		int sum = 0;
  		for(int j = 1; j <= n; j++){
   			sum += graph[j][i];
  		}
  		degree[i] = sum;
 	}
}
bool topology_sort(int n){
 	//stack<int> s;
 	queue<int> s;
 	int count = 0;
 	for(int i = 1; i <= n; i++){
  		if(degree[i] == 0)
   			s.push(i);
 	}
 	while(!s.empty()){
  		//int t = s.top();栈 
  		//s.pop();
  		int t = s.front();//队列 
  		for(int i = 1; i <= n; i++){
   			if(graph[t][i] != 0){
    				degree[i]--;
    				if(degree[i] == 0)
     				s.push(i);
   			}
  		} 
  		seq[count++] = t;
  		s.pop();
 	}
 	if(count == n) return true;
 	else return false;
}

int main(){
 	int n, m;
 	cin >> n >> m;
 	init_arry();
 	init_graph(m);
 	get_degree(n);
 	if(topology_sort(n)){
  	for(int i = 0; i < n; i++)
   		cout << seq[i] << " ";
 	}
 	return 0;
}

也可以通过记录拓扑序列的数组查看图中是否有环(AOV-网是有向无环图)。排序过程中只有无前驱的节点才会被记录,若存在环,则不会被记录。因此最终比较数组和顶点的大小便可确定是否存在环。
此外,通过打印记录数组可以发现,使用栈和队列的记录顺序是不同的。正确性毋庸置疑,因此可以得出拓扑排序序列不唯一的结论

猜你喜欢

转载自blog.csdn.net/qq_42017331/article/details/101849457