算法 - 拓扑算法与实现

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * 该类演示拓扑排序的算法与实现
 */
public class Main {
    public static List<Integer> topologicalSorting(int n, int[][] vertexMatrix) {
        // 创建一个用于输出拓扑排序结果的集合,入度为0的顶点会一次添加到此列表中
        List<Integer> topoRes = new ArrayList<>();
        // 1、首先是要创建一个数组对象,用于保存结点的入度
        int[] inDegree = new int[n];

        // 遍历所有所有子结点的,得到结点的入度并保存
        for (int i = 0; i < vertexMatrix.length; i++) {
            int child = vertexMatrix[i][1];
            inDegree[child]++;
        }

        // 创建一个队列,用于将入度为0的顶点放入其中
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }

        // 从队列中取值
        while (!queue.isEmpty()) {
            int curr = queue.poll(); // 取出
            topoRes.add(curr); // 添加到输出结果中
            // 循环遍历,找出父结点等于curr的结点,将他的子节点的入度减去1
            // 因为已经从有向图中取出了父节点
            for (int i = 0; i < vertexMatrix.length; i++) {
                int parent = vertexMatrix[i][0];
                // 判断,如果父节点等于curr,则将其子节点的入度减去1
                if (parent == curr) {
                    int child = vertexMatrix[i][1];
                    inDegree[child]--;
                    // 子节点的入度减去1之后,如果入度为0,则可以添加到队列
                    if (inDegree[child] == 0) {
                        queue.offer(child);
                    }
                }
            }
        }
        // 如果对有向图进行拓扑排序后,结果集合的大小小于节点数,说明该有向图不是“有向无环图”
        // 那么无法进行拓扑排序,返回空集合。
        return topoRes.size() == n ? topoRes : new ArrayList<>();
    }

    public static void main(String[] args) {
        // write your code here
        int n = 5;
        int[][] vertexMatrix = {{0, 1}, {0, 2}, {1, 2}, {1, 3}, {2, 3}, {4, 3}, {2, 4}};
        System.out.println(topologicalSorting(n, vertexMatrix));
    }
}

 

posted @ 2020-12-09 21:44  Runmoxin  阅读(273)  评论(0编辑  收藏  举报