【问题标题】:Implementing Dijkstra's Algorithm Using Directed Graphs使用有向图实现 Dijkstra 算法
【发布时间】:2016-03-26 18:08:36
【问题描述】:

我正在尝试通过邻接列表使用有向图来实现 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 找到原始示例代码的地方

【问题讨论】:

  • 你应该做一些调试。
  • 在什么方面?据我所知,我填充 ArrayList 的方法是正确的。我只是在努力解决如何将其转换为图表。
  • 我们可以看看您的输入文件的样本吗?
  • 我已更新帖子以添加它
  • 在这两种算法尝试中,您在哪里使用从输入数据创建的Graph.Edgelistedge 变量似乎没有在其他地方使用。

标签: java graph dijkstra directed-graph adjacency-list


【解决方案1】:

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

像这样使用您的代码(我已将 cmets 放在已更改的行上):

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

【讨论】:

  • 这是它的工作演示:Ideone Demo 虽然我使用了System.in 而不是文件。 (滚动到网页底部查看输入和输出)
  • 也许这是我的某个地方的一个小错误,但是当我运行它时,我收到开始和结束顶点不在图中的错误。我相信这与我上传文件的方式有关。我现在正在看。
  • 您是否使用了文件中实际存在的STARTEND 值?
  • 我现在似乎已经解决了所有的错误。感谢您的帮助
  • 太棒了!祝你有美好的一天:)
猜你喜欢
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-25
相关资源
最近更新 更多