修改Dijkstra以保存具有相等值的路径 - StackOverflow错误

时间:2017-10-16 20:00:22

标签: java stack-overflow dijkstra

我正在尝试修改Dijkstra的算法以显示具有最小值的所有路径。所以我决定使用以前的顶点列表。我添加了一个if子句,它检查路径是否是前一个具有最小值的igual我将前一个顶点添加为当前顶点的父节点。 问题是我收到了StackOverflow错误,我不知道是什么导致它。 这是我的代码: 下面代码的目的是为图中的所有顶点计算Dijkstra,计算顶点在找到的最小路径中出现的次数,并以所有这些顶点的顺序显示。

public class Dijkstra {

    public static final Map<String, Integer> ordem = new HashMap<>();

    public static void main(String[] args) throws FileNotFoundException, IOException {
        List<Graph.Edge> edges = new ArrayList<>();

        try {
            FileReader arq = new FileReader("input.txt");
            BufferedReader fw = new BufferedReader(arq);
            String linha = "";
            while (fw.ready()) {
                linha = fw.readLine();
                if (!linha.equals("0,0,0")) {
                    String parts[] = linha.split(",");
                    ordem.put(parts[0], 0);
                    ordem.put(parts[1], 0);
                    Graph.Edge a = new Graph.Edge(parts[0], parts[1], 100 - Integer.parseInt(parts[2]));
                    edges.add(a);
                } else {
                    break;
                }

            }
            fw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        Graph g = new Graph(edges);

        for (int i = 0; i < 5; i++) {
            g.dijkstra(String.valueOf(i));
            g.printAllPaths();
        }

        Object[] a = ordem.entrySet().toArray();
        Arrays.sort(a, new Comparator() {
            public int compare(Object o1, Object o2) {
                return ((Map.Entry<String, Integer>) o2).getValue()
                        .compareTo(((Map.Entry<String, Integer>) o1).getValue());
            }
        });
        for (Object e : a) {
            System.out.print(((Map.Entry<String, Integer>) e).getKey() + " ");
        }
        System.out.println("\n");
    }
}

class Graph {

    private final Map<String, Vertex> graph;

    public static class Edge {

        public final String v1, v2;
        public final int dist;

        public Edge(String v1, String v2, int dist) {
            this.v1 = v1;
            this.v2 = v2;
            this.dist = dist;
        }
    }

    public static class Vertex implements Comparable<Vertex> {

        public final String name;
        public int dist = Integer.MAX_VALUE; 
        public List<Vertex> previous = new ArrayList<>();
        public final Map<Vertex, Integer> neighbours = new HashMap<>();

        public Vertex(String name) {
            this.name = name;
        }

        private void printPath() {
            if (this == this.previous) {
            } else if (this.previous == null) {
            } else {
                //This is where I am getting the error
                for (int i = 0; i<this.previous.size(); i++){
                this.previous.get(i).printPath();
                Dijkstra.ordem.replace(this.name, Dijkstra.ordem.get(this.name) + 1);
            }

            }
        }

        public int compareTo(Vertex other) {
            if (dist == other.dist) {
                return name.compareTo(other.name);
            }

            return Integer.compare(dist, other.dist);
        }

        @Override
        public String toString() {
            return "(" + name + ", " + dist + ")";
        }
    }

    public Graph(List<Graph.Edge> edges) {
        graph = new HashMap<>(edges.size());

        for (Edge e : edges) {
            if (!graph.containsKey(e.v1)) {
                graph.put(e.v1, new Vertex(e.v1));
            }
            if (!graph.containsKey(e.v2)) {
                graph.put(e.v2, new Vertex(e.v2));
            }
        }

        for (Edge e : edges) {
            graph.get(e.v1).neighbours.put(graph.get(e.v2), e.dist);
            graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist);
        }
    }


    public void dijkstra(String startName) {
        if (!graph.containsKey(startName)) {
            System.err.printf("Graph doesn't contain start vertex \"%s\"\n", startName);
            return;
        }
        final Vertex source = graph.get(startName);
        NavigableSet<Vertex> q = new TreeSet<>();

        // Inicializacao dos vertices
        for (Vertex v : graph.values()) {
            //v.previous = v == source ? list : null;
            if (v == source) {
                v.previous.add(source);
            } else {
                v.previous = new ArrayList<>();
            }
            v.dist = v == source ? 0 : Integer.MAX_VALUE;
            q.add(v);
        }

        dijkstra(q);
    }

    private void dijkstra(final NavigableSet<Vertex> q) {
        Vertex u, v;
        while (!q.isEmpty()) {

            u = q.pollFirst(); 
            if (u.dist == Integer.MAX_VALUE) {
            }
            for (Map.Entry<Vertex, Integer> a : u.neighbours.entrySet()) {
                v = a.getKey(); 

                final int alternateDist = u.dist + a.getValue();
                if (alternateDist < v.dist) {
                    q.remove(v);
                    v.dist = alternateDist;
                    v.previous.add(u);
                    q.add(v);
                } else if(alternateDist == v.dist) {
                    v.previous.add(u);
                }
            }
        }
    }


    public void printPath(String endName) {
        if (!graph.containsKey(endName)) {
            System.err.printf("Graph doesn't contain end vertex \"%s\"\n", endName);
            return;
        }

        graph.get(endName).printPath();
        //System.out.println();
    }

    public void printAllPaths() {
        for (Vertex v : graph.values()) {
            v.printPath();
        }
    }
}

这是错误:

Exception in thread "main" java.lang.StackOverflowError
    at Graph$Vertex.printPath(Dijkstra.java:117)
    at Graph$Vertex.printPath(Dijkstra.java:118)

1 个答案:

答案 0 :(得分:0)

正如错误消息已经暗示:你的dijkstra不是问题所在。 问题是printPath()调用自己。

可能是罪魁祸首

if (this == this.previous) {} ...

您将Vertex thisList<Vertex> previous进行比较。也许你想检查

if (this == this.previous.get(this.previous.size() - 1)) {} ...

代替。

我没有对此进行测试,因为您的代码(1.)太长而且(2.)不是自包含的(至少缺少“input.txt”)。