拓扑排序(邻接表存储图)

1. 拓扑排序是将有向图G的所有顶点排成一个线性序列,使得对图G中的任意两个顶点u,v如果存在边u,v那么序列中u一定是在v的前面,这个序列有被称为是拓扑序列

所以拓扑排序是针对于有向图的,是用来判定有向图中是否存在环(深度优先搜索也可以判定有向图是否有环)

2. 拓扑排序的执行过程如下:

① 定义一个队列,并把所有入度为0的节点加入到队列中去

② 取出队首节点,输出,然后删除所有从它发出的边,并且令这些边到达的顶点的入度减1,判断某个顶点入度是否为0假如是0那么加入到队列中

③ 反复执行②操作直到队列为空,如果队列为空的时候入对的节点的数目恰好是N,说明拓扑排序成功否则拓扑排序失败,图是存在环的

3. 下面使用Java语言来完成编程过程:

① 首先需要解决图的存储方式的问题,这里我们选择使用邻接表的方式来存储图,可以声明一个集合数组,数组中的每一个元素都是一个集合,那么就可以模仿创建的链表了,数组的下标表示顶点的编号

② 由于需要记录节点的入度,所以需要额外建立一个数组来记录节点的入度,并且在程序读入图的时候就记录好每一个节点的入度

测试数据如下:

5
6
0 1
0 2
0 3
1 4
2 4
3 4

4. 具体的代码如下:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
public class Main {
	static int n = 0;
	static int edgesNum = 0;
	static int inDegree[];
	static int count = 0;
	static List<Integer> graph [];
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("输入图中顶点的个数: ");
		n = sc.nextInt();
		inDegree = new int[n];
		System.out.println("输入图中边的条数: ");
		edgesNum = sc.nextInt();
		//创建一个List数组
		graph = new ArrayList[n];
		for(int i = 0; i < n; i++){
			//初始化每一个集合中元素
			graph[i] = new ArrayList<Integer>();
		}
		System.out.println("输入图中边的起始顶点, 结束顶点和顶点之间的权值: ");
		for(int i = 0; i < edgesNum; i++){
			int u = sc.nextInt();
			int v = sc.nextInt();
			graph[u].add(v);
			inDegree[v]++;
		}
		boolean res = topologicalSort();
		if(res){
			System.out.println("拓扑排序成功");
		}else{
			System.out.println("拓扑排序失败");
		}
		sc.close();
	}
	
	private static boolean topologicalSort() {
		Queue<Integer> queue = new LinkedList<Integer>();
		//检查入度为零的顶点
		for(int i = 0; i < n; i++){
			if(inDegree[i] == 0){
				queue.add(i);
				//System.out.println(i);
			}
		}
		while(!queue.isEmpty()){
			int u = queue.poll();
			//输出拓扑排序序列
			System.out.print(u + " ");
			for(int i = 0; i < graph[u].size(); i++){
				int v = graph[u].get(i);
				inDegree[v]--;
				if(inDegree[v] == 0)queue.add(v); 
			}
			//记录访问过的节点的数目
			count++;
		}
		if(count == n) return true;
		return false;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/91959284
今日推荐