17.4: Topological sorting of graphs

The topological order must be a directed acyclic graph.

Topological sort is not unique

insert image description here
insert image description here

Topological sorting method one:

Sort with in-degree zero

Idea: Whoever has an in-degree of 0 is the start node. After printing the start node, reduce the in-degree of the direct neighbors of the start node by 1, and repeat.

insert image description here

package algorithmbasic.class17;

import java.util.*;

//图的拓扑排序
public class TopologySort {
    
    
    public static List<Node> sortedTopology(Graph graph) {
    
    
        //result用来盛放排序结果。
        List<Node> result = new ArrayList<>();
        //inmap存放节点与入度的对应值。
        //key ——> 某个节点, value ——> 剩余入度
        HashMap<Node, Integer> inmap = new HashMap<>();
        //只有节点的入度为0才可以进入此队列。
        Queue<Node> inZeroQueue = new LinkedList<>();

        for (Node node : graph.nodes.values()) {
    
    
            inmap.put(node, node.in);
            if (node.in == 0) {
    
    
                inZeroQueue.add(node);
            }
        }

        Node cur = inZeroQueue.poll();
        result.add(cur);
        for (Node next : cur.nexts) {
    
    
            //剩余入度减1.
            inmap.put(next, inmap.get(next) - 1);
            if (inmap.get(next) == 0) {
    
    
                inZeroQueue.add(next);
            }
        }
        return result;
    }
}

Topological sorting method two:

Sort by point.

insert image description here

The larger the number of points, the higher the sorting position.

And I found that recursion can be used to find points. If we ask for the points of 0, then we need to ask for the points of his direct neighbors 1, 2, and 3, and then add 1 to the sum of the points of the neighbors, which is the point of 0. We can put the points of each point in a table, and this table records which node's points correspond to how many. In this way, when we ask for other node points, we can just take them directly from the table, reducing repetitive work.

Ideas:
1: Create a table HashMap<DirectedGraphNode, Record> order = new HashMap<>() to record the number of points corresponding to each node.

2: Traverse every node in the entire graph and record its point times.

3: Create an ordered table ArrayList records = new ArrayList<>() to record points.

4: Sorting from large to small according to the number of points. records. sort(new MyComparator());

5: Then create an ordered table ArrayList dnodes = new ArrayList<>() to record nodes according to the order of points.

Note why the inner class Record was created. Because when "recording nodes according to the order of points", we need to find the corresponding nodes according to the points. It is not possible to use map, because the size of the points is repeated. So we use the inner class method, so that each point will have a one-to-one corresponding node.

package algorithmbasic.class17;
//图的拓扑排序方法二

import java.util.*;

// OJ链接:https://www.lintcode.com/problem/topological-sorting
public class TopologicalOrderDFS2 {
    
    
    /**
     * 节点内部类
     */
    // 不要提交这个类
    public static class DirectedGraphNode {
    
    
        public int label;
        public ArrayList<DirectedGraphNode> neighbors;

        public DirectedGraphNode(int x) {
    
    
            label = x;
            neighbors = new ArrayList<DirectedGraphNode>();
        }
    }
    
    /**
     * 点次内部类。
     */

    //记录某个节点的点次。
    public static class Record {
    
    
        public DirectedGraphNode node;
        //点次。
        public long nodes;

        public Record(DirectedGraphNode node, long nodes) {
    
    
            this.node = node;
            this.nodes = nodes;
        }
    }

    /**
     * topSort方法
     * 传入一张图的所有节点,返回排序好后的所有节点。
     */

    public static ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
    
    
        //采用计算每个节点点次的方法。
        //建立一张表用来记录每个节点对应的点次是多少。
        HashMap<DirectedGraphNode, Record> order = new HashMap<>();
        ArrayList<Record> records = new ArrayList<>();
        ArrayList<DirectedGraphNode> dnodes = new ArrayList<>();

        //遍历图中每个节点,并记录每个节点出现的点次。
        for (DirectedGraphNode cur : graph) {
    
    
            Record record = process(cur, order);
            records.add(record);
            //order.put(cur, record);
        }
        //Arrays.sort(records,new MyComparator());
        records.sort(new MyComparator());
        for (Record r : records) {
    
    
            dnodes.add(r.node);//这就是为什么要建立Record这个内部类的原因。
        }
        return dnodes;
    }
    
    /**
     * 求点次的方法。
     */

    //传入一个节点返回这个节点的点次。在递归的过程当中每个节点的点次其实都已经记录好了。
    public static Record process(DirectedGraphNode node, HashMap<DirectedGraphNode, Record> order) {
    
    
        if (order.containsKey(node)) {
    
    
            return order.get(node);
        }
        //order中没有该点。
        long count = 0;
        for (DirectedGraphNode n : node.neighbors) {
    
    
            Record r = process(n, order);
            count += r.nodes;
        }
        Record record = new Record(node, count + 1);
        //先把当前节点及其点次放入map中然后再返回。这样我们再求其他节点点次时直接从表里拿就行,减少重复性工作。
        order.put(node, record);
        return record;
    }

    /**
     * 比较器
     */
    
    public static class MyComparator implements Comparator<Record> {
    
    
        @Override
        public int compare(Record o1, Record o2) {
    
    
            //不要将long类型数据强制转换成int类型,会出现溢出和截断的风险,导致数据出现错误。
            //例如2147483648L -> int:-2147483648
            //它超过了int类型的最大值 2147483647。当将其强制转换为int类型时,结果被截断为int类型的最小值 -2147483648。
            //return (int)(o2.nodes - o1.nodes);
            return o1.nodes == o2.nodes ? 0 : (o1.nodes > o2.nodes ? -1 : 1);
        }
    }
}

Topological sorting method three:

sort by depth

insert image description here

package algorithmbasic.class17;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;

public class TopologicalOrderDFS1 {
    
    

    /**
     * 节点内部类
     */

    public static class DirectedGraphNode {
    
    
        public int label;
        public ArrayList<DirectedGraphNode> neighbors;

        public DirectedGraphNode(int x) {
    
    
            label = x;
            neighbors = new ArrayList<DirectedGraphNode>();
        }
    }

    /**
     * 深度内部类。
     */

    public static class Deep {
    
    
        public long deep;
        public DirectedGraphNode node;

        public Deep(long deep, DirectedGraphNode node) {
    
    
            this.deep = deep;
            this.node = node;
        }
    }

    /**
     * topSort方法
     */

    public static ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
    
    
        HashMap<DirectedGraphNode, Deep> order = new HashMap<>();
        ArrayList<Deep> deeps = new ArrayList<>();
        ArrayList<DirectedGraphNode> dNodes = new ArrayList<>();

        for (DirectedGraphNode node : graph) {
    
    
            Deep d = process(node, order);
            deeps.add(d);
        }
        deeps.sort(new MyComparator());
        for (Deep d : deeps) {
    
    
            dNodes.add(d.node);
        }
        return dNodes;
    }


    public static Deep process(DirectedGraphNode node, HashMap<DirectedGraphNode, Deep> order) {
    
    
        if (order.containsKey(node)) {
    
    
            return order.get(node);
        }
        long max = Long.MIN_VALUE;
        for (DirectedGraphNode n : node.neighbors) {
    
    
            Deep d = process(n, order);
            max = Math.max(max, d.deep);
        }
        Deep deep = new Deep(max + 1, node);
        order.put(node, deep);
        return deep;
    }

    public static class MyComparator implements Comparator<Deep> {
    
    
        @Override
        public int compare(Deep o1, Deep o2) {
    
    
            return o1.deep == o2.deep ? 0 : (o1.deep > o2.deep ? -1 : 1);
        }
    }
}

Guess you like

Origin blog.csdn.net/SCR1209/article/details/131024214
Recommended