使用有向图实现 Dijkstra 算法



我正试图通过邻接列表使用有向图来实现Dijkstra的算法。我发现了一些示例代码。在该代码中,图形填充如下:

private static final Graph.Edge[] GRAPH = {
    new Graph.Edge("a", "b", 7),
    new Graph.Edge("a", "c", 9),
    new Graph.Edge("a", "f", 14),
    new Graph.Edge("b", "c", 10),
    new Graph.Edge("b", "d", 15),
    new Graph.Edge("c", "d", 11),
    new Graph.Edge("c", "f", 2),
   new Graph.Edge("d", "e", 6),
    new Graph.Edge("e", "f", 9),};
private static final String START = "a";
private static final String END = "e";

由于我需要从文本文件中的邻接列表进行填充,因此我尝试以以下方式进行填充:

List<Graph.Edge> list = new ArrayList<>();
    try {
        Scanner scanner = new Scanner(new File(filename));
        while (scanner.hasNextLine()) {
            String source = scanner.findInLine(NAME);
            if (source != null) {
                while (true) {
                    String to = scanner.findInLine(NAME);
                    if (to == null) {
                        break;
                    }
                    int weight = Integer.valueOf(scanner.findInLine(WEIGHT));
                    list.add(new Graph.Edge(source, to, weight));
                }
            }
            scanner.nextLine();
        }
    } catch (FileNotFoundException | NumberFormatException e) {
    }

带有

static final Pattern NAME = Pattern.compile("\w+");
static final Pattern WEIGHT = Pattern.compile("\d+");

在示例代码中,他们以以下方式在图上运行dijkstra的算法:

Graph g = new Graph(GRAPH);
    g.dijkstra(START);
    g.printPath(END);
    g.printAllPaths();

我尝试更新我的代码,以便为该算法的实现工作。我想到了以下内容:

try {
        Scanner scanner = new Scanner(new File(filename));
        while (scanner.hasNextLine()) {
            String source = scanner.findInLine(NAME);
            if (source != null) {
                while (true) {
                    String go = scanner.findInLine(NAME);
                    if (go == null) {
                        break;
                    }
                    int weight = Integer.valueOf(scanner.findInLine(WEIGHT));
                    Graph.Edge edge = new Graph.Edge(source, go, weight);
                    Graph g = new Graph(GRAPH);
                    g.dijkstra(source);
                    g.printPath(go);
                }
            }
            scanner.nextLine();
        }
    } catch (FileNotFoundException | NumberFormatException e) {
    }

当我尝试运行这个程序时,它似乎没有正确地填充我的图形。它从dijkstra和printPath方法中产生错误,称"图形不包含起始/结束顶点。"我如何更新代码,使图形正确填充并能够正确实现算法?谢谢

编辑:这是我的输入文件的一个示例

1 2 1 3 1
2 4 2
3 2 2 5 4
4 3 3 5 3
5 1 4

它遵循格式来源,adj.顶点,权重,adj.顶部,权重。。。。

编辑2:图形边缘的使用`

class Graph {
private final Map<String, Vertex> graph; // mapping of vertex names to Vertex objects, built from a set of Edges
/**
 * One edge of the graph (only used by Graph constructor)
 */
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 Graph(Edge[] edges) {
    graph = new HashMap<>(edges.length);
    //one pass to find all vertices
    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));
        }
    }
    //another pass to set neighbouring vertices
    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); // also do this for an undirected graph
    }
}

编辑:这是我从哪里找到的原始示例代码http://rosettacode.org/wiki/Dijkstra%27s_algorithm#Java

为了使用带有文件输入的应用程序,请使用您的第一个文件输入算法。除非您想将文件的每一行作为只有一个VertexGraph运行,否则第二种算法是无用的。

这样使用你的代码(我已经在我更改的行上添加了注释):

private static final Graph.Edge[] GRAPH = getEdges("input.txt"); // <-- CHANGED THIS
private static final String START = "1"; // <-- CHANGED THIS
private static final String END = "5"; // <-- CHANGED THIS
private static Graph.Edge[] getEdges(String fileName) { // <-- ADDED THIS
    final Pattern NAME = Pattern.compile("\w+");
    final Pattern WEIGHT = Pattern.compile("\d+");
    List<Graph.Edge> list = new ArrayList<>();
    try {
        Scanner scanner = new Scanner(new File(fileName));
        while (scanner.hasNextLine()) {
            String source = scanner.findInLine(NAME);
            if (source != null) {
                while (true) {
                    String to = scanner.findInLine(NAME);
                    if (to == null) {
                        break;
                    }
                    int weight = Integer.valueOf(scanner.findInLine(WEIGHT));
                    list.add(new Graph.Edge(source, to, weight));
                }
            }
            if (scanner.hasNextLine()) // <-- ADDED THIS
                scanner.nextLine();
        }
    } catch (FileNotFoundException | NumberFormatException e) {
    }
    return list.toArray(new Graph.Edge[0]); // <-- ADDED THIS
}

然后,以相同的方式运行应用程序:

Graph g = new Graph(GRAPH);
g.dijkstra(START);
g.printPath(END);
g.printAllPaths();

我测试了所有这些,还发现您的文件输入算法在文件的最后一行中断,所以我在scanner.nextLine(); 之前添加了if (scanner.hasNextLine())

最新更新