簡體   English   中英

使用有向圖實現Dijkstra算法

[英]Implementing Dijkstra's Algorithm Using Directed Graphs

我試圖通過鄰接表使用有向圖來實現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。 頂點,重量,調整 頂點,重量...

編輯2:使用Graph.Edge`

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

我測試了所有這些,還發現您的文件輸入算法在文件的最后一行中斷,因此我if (scanner.hasNextLine())之前添加了if (scanner.hasNextLine()) scanner.nextLine();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM