算法第四版 P426 无环加权有向图最短路径算法实现

本算法为处理无环加权有向图的算法,需要用到最短路径以及拓扑排序,所以,在图中不能存在有向环,否则数据错误,本算法的拓扑排序理论来自于之前的Kosaraju算法,即通过反图的拓扑排序顺序来遍历原图中的所有节点,因为不用判断节点是否被访问,所以不需要布尔数组判断点是否可用。

这里要特别指出书中的一个错误,P427顶端的第一幅图上方的拓扑排序的顺序应为:5,1,3,6,4,0,7,2

本算法由四个类组成,下面是各个类的源代码:

AcyclicSP
package com;

public class AcyclicSP {

    private DirectedEdge[] edgeTo;
    private double[] distTo;

    public AcyclicSP(EdgeWeightedDigraph G) {
        edgeTo = new DirectedEdge[G.V()];
        distTo = new double[G.V()];
        for (int i = 0; i < G.V(); i++)
            distTo[i] = Double.POSITIVE_INFINITY;
        distTo[5] = 0;
        Topological topological = new Topological(G.reverse());
        Iterable list = topological.order();
        for (int v : list) {
            relax(G,v);
        }
    }

    public void relax(EdgeWeightedDigraph G, int v) {
        for (DirectedEdge e : G.adj(v)) {
            int w = e.to();
            if (distTo[w] > distTo[v] + e.getWeight()) {
                edgeTo[w] = e;
                distTo[w] = distTo[v] + e.getWeight();
            }
        }
    }

    public static void main(String[] args) {
        EdgeWeightedDigraph graph = new EdgeWeightedDigraph(8);
        DirectedEdge[] edges = {
                new DirectedEdge(5,4,0.35),
                new DirectedEdge(4,0,0.38),
                new DirectedEdge(4,7,0.37),
                new DirectedEdge(5,7,0.28),
                new DirectedEdge(5,1,0.32),
                new DirectedEdge(0,2,0.26),
                new DirectedEdge(3,7,0.39),
                new DirectedEdge(1,3,0.29),
                new DirectedEdge(7,2,0.34),
                new DirectedEdge(6,2,0.40),
                new DirectedEdge(3,6,0.52),
                new DirectedEdge(6,0,0.58),
                new DirectedEdge(6,4,0.93)
        };
        for (DirectedEdge edge : edges)
            graph.addEdge(edge);
        AcyclicSP sp = new AcyclicSP(graph);
        for (int i = 0; i < graph.V(); i++)
            System.out.println(i+" Edge = "+sp.edgeTo[i]+" dist = "+sp.distTo[i]);
    }
}

DirectedEdge
package com;

public class DirectedEdge {

    private final int w;
    private final int v;
    private final double weight;

    public DirectedEdge(int v, int w, double weight) {
        this.v = v;
        this.w = w;
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }

    public int from() {
        return v;
    }

    public int to() {
        return w;
    }

    @Override
    public String toString() {
        return "DirectedEdge{" +
                "w=" + w +
                ", v=" + v +
                ", weight=" + weight +
                '}';
    }
}

EdgeWeightedDigraph
package com;

import java.util.ArrayList;

public class EdgeWeightedDigraph {

    private int V;
    private int E;
    private ArrayList[] adj;

    public EdgeWeightedDigraph(int v) {
        this.V = v;
        this.E = 0;
        adj = new ArrayList[v];
        for (int i = 0; i < V; i++)
            adj[i] = new ArrayList();
    }

    public int V() {
        return V;
    }

    public int E() {
        return E;
    }

    public void addEdge(DirectedEdge e) {
        int v = e.from();
        adj[v].add(e);
        E++;
    }

    public Iterable adj(int v) {
        return adj[v];
    }

    public Iterable edges() {
        ArrayList edgesArr = new ArrayList<>();
        for (int i = 0; i < V; i++) {
            for (DirectedEdge e : adj[i]) {
                edgesArr.add(e);
            }
        }
        return edgesArr;
    }

    public EdgeWeightedDigraph reverse() {
        EdgeWeightedDigraph newGraph = new EdgeWeightedDigraph(8);
        for (int i = 0; i < V; i++) {
            for (DirectedEdge e : adj(i)) {
                DirectedEdge edge = new DirectedEdge(e.to(),e.from(),e.getWeight());
                ((ArrayList)newGraph.adj(e.to())).add(edge);
            }
        }
        return newGraph;
    }

}

Topological
package com;

import java.util.Stack;

public class Topological {

    private boolean[] visited;
    private Stack reservePost;

    public Topological(EdgeWeightedDigraph G) {
        visited = new boolean[G.V()];
        reservePost = new Stack<>();
        for (int i = 0; i < G.V(); i++) {
            if (!visited[i])
                dfs(G,i);
        }
    }

    public void dfs(EdgeWeightedDigraph G, int v) {
        visited[v] = true;
        for (DirectedEdge e : G.adj(v)) {
            int w = e.to();
            if (!visited[w])
                dfs(G,w);
        }
        reservePost.push(v);
    }

    public Iterable order() {
        return reservePost;
    }

}

输出结果:




你可能感兴趣的:(数据结构入门)