17.4: Ordenação topológica de gráficos

A ordem topológica deve ser um grafo acíclico direcionado.

A ordenação topológica não é única

insira a descrição da imagem aqui
insira a descrição da imagem aqui

Método de classificação topológica um:

Ordenar com grau zero

Ideia: Aquele que tiver grau de entrada 0 é o nó inicial.Após imprimir o nó inicial, reduza o grau de entrada dos vizinhos diretos do nó inicial em 1 e repita.

insira a descrição da imagem aqui

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 classificação topológica dois:

Classificar por ponto.

insira a descrição da imagem aqui

Quanto maior o número de pontos, maior a posição de classificação.

E descobri que a recursão pode ser usada para encontrar pontos. Se pedirmos os pontos de 0, precisamos pedir os pontos de seus vizinhos diretos 1, 2 e 3, e então adicionar 1 à soma dos pontos dos vizinhos, que é o ponto de 0. Podemos colocar os pontos de cada ponto em uma tabela, e esta tabela registra quais pontos do nó correspondem a quantos. Dessa forma, quando solicitamos outros pontos de nó, podemos apenas retirá-los diretamente da mesa, reduzindo o trabalho repetitivo.

Idéias:
1: Criar uma tabela HashMap<DirectedGraphNode, Record> order = new HashMap<>() para registrar o número de pontos correspondentes a cada nó.

2: Percorra cada nó em todo o grafo e registre seus tempos de ponto.

3: Crie uma tabela ordenada ArrayList records = new ArrayList<>() para registrar pontos.

4: Classificando de grande para pequeno de acordo com o número de pontos. registros sort(new MyComparator());

5: Em seguida, crie uma tabela ordenada ArrayList dnodes = new ArrayList<>() para registrar os nós de acordo com a ordem dos pontos.

Observe por que a classe interna Record foi criada. Porque ao "registrar os nós de acordo com a ordem dos pontos", precisamos encontrar os nós correspondentes de acordo com os pontos. Não é possível usar o mapa, porque o tamanho dos pontos é repetido. Portanto, usamos o método de classe interna, para que cada ponto tenha um nó correspondente um-para-um.

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 classificação topológica três:

classificar por profundidade

insira a descrição da imagem aqui

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

Acho que você gosta

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