17.4: Clasificación topológica de gráficos

El orden topológico debe ser un gráfico acíclico dirigido.

La clasificación topológica no es única.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Método de clasificación topológica uno:

Ordenar con grado cero

Idea: El nodo de inicio es quien tiene un grado de entrada 0. Después de imprimir el nodo de inicio, reduzca el grado de entrada de los vecinos directos del nodo de inicio en 1 y repita.

inserte la descripción de la imagen aquí

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;
    }
}

Método de clasificación topológica dos:

Ordenar por punto.

inserte la descripción de la imagen aquí

Cuanto mayor sea el número de puntos, mayor será la posición de clasificación.

Y descubrí que la recursividad se puede usar para encontrar puntos. Si preguntamos por los puntos de 0, entonces necesitamos preguntar por los puntos de sus vecinos directos 1, 2 y 3, y luego sumar 1 a la suma de los puntos de los vecinos, que es el punto de 0. Podemos poner los puntos de cada punto en una tabla, y esta tabla registra qué puntos de nodo corresponden a cuántos. De esta forma, cuando solicitamos otros puntos de nodo, podemos simplemente tomarlos directamente de la tabla, reduciendo el trabajo repetitivo.

Ideas:
1: Crear una tabla HashMap<DirectedGraphNode, Record> order = new HashMap<>() para registrar el número de puntos correspondientes a cada nodo.

2: Atraviese cada nodo en todo el gráfico y registre sus puntos de tiempo.

3: Cree una tabla ordenada ArrayList records = new ArrayList<>() para registrar puntos.

4: Clasificación de mayor a menor según el número de puntos. registros.sort(nuevo MiComparador());

5: Luego cree una tabla ordenada ArrayList dnodes = new ArrayList<>() para registrar los nodos según el orden de los puntos.

Tenga en cuenta por qué se creó la clase interna Registro. Porque al "registrar nodos según el orden de los puntos", necesitamos encontrar los nodos correspondientes según los puntos. No es posible usar el mapa, porque el tamaño de los puntos se repite. Entonces usamos el método de clase interna, de modo que cada punto tendrá un nodo correspondiente uno a uno.

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);
        }
    }
}

Método de clasificación topológica tres:

ordenar por profundidad

inserte la descripción de la imagen aquí

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);
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/SCR1209/article/details/131024214
Recomendado
Clasificación