跟着左神学算法:P7 图

144 阅读1分钟

P7 图

图的存储形式

  1. 邻接表
  2. 邻接矩阵

public class Graph {
    Map<Integer, Node> nodes;
    List<Edge> edges;

    Graph() {

     }

    Graph(Map<Integer, Node> nodes, List<Edge> edges) {
        this.nodes = nodes;
        this.edges = edges;
    }
}

public class Edge {
    int from;
    int to;
    int weight;

    Edge(int from, int to, int weight) {
        this.from = from;
        this.to = to;
        this.weight = weight;
    }
}

public class Node {
    int value;
    int in;
    int out;
    public List<Node> nexts;
    public List<Edge> edges;
}

图的遍历

宽度优先遍历

  1. 利用队列实现
  2. 从源节点开始把相邻的点加入队列
  3. 每弹出一个点,就把它的没进过队列的邻接点放进队列,一直遍历到队列为空
    public void bfs(Node source) {
        if(source == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        Set<Node> set = new HashSet<>();
        while(!queue.isEmpty()) {
            Node node = queue.poll();
            System.out.print(node);
            for(Node next : node.nexts) {
                if(!set.contain(next)) {
                    queue.add(next);
                    set.add(next);
                }
            }
        }
    }

深度优先遍历

    public void dfs(Node source) {
        if(source == null) {
            return;
        }
        Stack<Node> stack = new Stack<>();
        Set<Node> set = new HashSet<>();
        stack.push(source);
        set.add(source);
        System.out.print(source);
        while(!stack.isEmpty()){
            Node node = stack.pop();
            for(Node next : node.nexts) {
                if(!set.contain(next)) {
                    stack.push(node);
                    stack.push(next);
                    set.add(next);
                    System.out.print(next);
                    break;
                }
            }  
        }
    }

拓扑排序算法

把节点按照依赖顺序输出

public List<Node> sort(Graph graph) {
    HashMap<Node, Integer> inMap = new HashMap<>();
    Queue<Node> zeroInQueue = new LinkedList<>();
    for(Node node : graph.nodes.values) {
        inMap.put(node, node.in);
        if(node.in == 0) {
            zeroInQueue.add(node);
        }
    }

    List<Node> result = new ArrayList<>();
    while(!zeroInQueue.isEmpty()) {
        Node cur = zeroInQueue.poll();
        result.add(cur);
        for(Node next : node.nexts){
            inMap.put(next, inMap.get(next) - 1);
            if(inMap.get(next) == 0) {
                zeroInQueue.add(next);
            }
        }
    }
    return result;
}

最小生成树

图连通同时权值最小

K算法(从边的角度出发)

从最小的边开始,如果不会形成环就把边加入

public Set<Edge> KMST(Graph graph) {
    UnionFind unionFind = new UnionFind();
    unionFind.makeSets(graph.nodes.values());
    PriorityQueue<Edge> queue = new PriorityQueue<>((i,j) -> i.weight - j.weight);
    for(Edge edge : graph.edges) {
        queue.add(edge);
    }
    Set<Edge> res = new HashSet<>();
    while(!queue.isEmpty()) {
        Edge edge = queue.poll();
        if(!unionFind.isSameSet(edge.from, edge.to)) {
            res.add(edge);
            unionFind.union(edge.from, edge.to);
        }
    }
    return res;
}

P算法(从点的角度出发)

要求无向图

public Set<Edge> primMST(Graph graph) {
    PriorityQueue<Edge> queue = new PriorityQueue<>((e1, e2) -> e1.weight - e2.weight);
    HashSet<Node> set = new HashSet<>();

    Set<Edge> result = new HashSet<>();
    for(Node node : graph.nodes.values) {
        if(!set.contains(node)) {
            set.add(node);
            for(edge edge : node.edges) {
                queue.add(edge);
            }
            while(!queue.isEmpty()) {
                Edge edge = queue.poll();
                Node toNode = edge.to;
                if(!set.contains(toNode)) {
                    set.add(toNode);
                    result.add(edge);
                    for(Edge nextEdge : toNode.edges) {
                        queue.add(nextEdge);
                    }
                }
            }
        }
    }
    return result;
}

迪杰斯特拉算法

从 A 到其他点最短路径

要求权值不能为负数(严格来说,不能有累加和为负数的环)

public HashMap<Node, Integer> dijkstra(Node head) {
    HashMap<Node, Integer> distanceMap = new HashMap<>();
    distanceMap.put(head, 0);
    HashSet<Node> selectedNodes = new HashSet<>();
    Node minNode = getMinDistanceAndUnselectedNode(distanceMao, selectedNodes);
    while(minNode != null) {
        int distance = distanceMap.get(minNode);
        for(Edge edge : minNode.edges) {
            Node toNode = edge.to;
            if(!disatnceMao.containsKey(toNode)) {
                distanceMap.put(toNode, distance + edge.weight);
            }
            distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));
        }
        selectedNodes.add(minNode);
        minNode = getMinDistanceAndUnselectedNode(distanceMao, selectedNodes);
    }
    return distanceMap;
}