簡體   English   中英

Dijkstra 算法自身的實現問題

[英]Dijkstra´s algorithm own implementation problem

我在一個簡單的 Graph 類中使用了這個 Dijkstra 算法 O(n^2) 實現,在調試它時,輸出與 JUnit 測試中的預期輸出不同,我找不到問題:

    public void Dijkstra(T departureNode) {
    initDijkstra(departureNode);

    ArrayList<GraphNode<T>> V_S = fillWithoutElement(departureNode);

    while (V_S.size() > 0) {
        int w  = chooseMinimum(D);
        nodes.get(w).setVisited(true);
        GraphNode<T> auxW = nodes.get(w);
        V_S.remove(findOnV_S(V_S, auxW));

        for(GraphNode<T> m : V_S) {
            if (D[w] + weights[w][getNode(m.getElement())] < D[getNode(m.getElement())]) {
                D[getNode(m.getElement())] = D[w] + weights[w][getNode(m.getElement())];
                PD[getNode(m.getElement())] = w;
            }
        }
    }
}

這是輔助方法chooseMinimum():

    private int chooseMinimum(double[] auxD) {
    int res = 0;
    double min = INFINITE;
    for (int i = 0; i < auxD.length; i++) {
        if (!nodes.get(i).isVisited()) {
            if (auxD[i] < min) {
                min = auxD[i];
                res = i;
            }
        }
    }
    return res;
}

這是 findOnV_S() 方法:

    private int findOnV_S(ArrayList<GraphNode<T>> V_S, GraphNode<T> auxW) {
    int res = 0;
    for(int i = 0; i < V_S.size(); i++) {
        if(V_S.get(i).equals(auxW))
            res = i;
    }
    return res;
}

這是 initDijkstra() 方法:

public void initDijkstra(T departureNode) {
    if (!itExists(departureNode))
        throw new IllegalArgumentException("Node does not exist");

    D = new double[size];
    PD = new int[size];
    int j = getNode(departureNode);
    // Initialize D
    for (int i = 0; i < size; i++) {
        if (edges[j][i]) {
            D[i] = weights[j][i];
        } else
            D[i] = INFINITE;
    }

    // Initialize PD
    for (int i = 0; i < size; i++) {
        if (edges[j][i])
            PD[i] = getNode(departureNode);
        else
            PD[i] = EMPTY;
    }

    initializeVisitedToFalseExceptStart(departureNode);
}

這是 initializeVisitedToFalseExceptStart 輔助方法:

    private void initializeVisitedToFalseExceptStart(T departureNode) {
    if (!itExists(departureNode))
        throw new RuntimeException("Invalid node");
    GraphNode<T> element = null;
    for (int i = 0; i < size; i++) {
        element = nodes.get(i);
        if ((element.getElement()).equals(departureNode))
            element.setVisited(true);
        else
            nodes.get(i).setVisited(false);
    }
}

PD:我認為錯誤的方法是chooseMinimum()

PD2:在下一個 JUnit 中,您將看到 getD() 將返回一個二維數組,但 Graph 類中的實際 D 是一個一維數組。

PD3:這是簡單的 JUnit 測試:

     try
     {
         g.addNode("V1");
         g.addNode("V2");
         g.addNode("V3");
         g.addNode("V4");
         g.addNode("V5");
         g.addNode("V6");
     }
     catch (Exception e)
     {
         System.out.println ("No repeated nodes are allowed" + e);
     }

     try
     {
         g.addEdge ("V1", "V2", 3.0);
         g.addEdge ("V1", "V3", 4.0);
         g.addEdge ("V1", "V5", 8.0);

         g.addEdge ("V2", "V5", 5.0);

         g.addEdge ("V3", "V5", 3.0);

         g.addEdge ("V5", "V6", 3.0);
         g.addEdge ("V5", "V4", 7.0);

         g.addEdge ("V6", "V4", 2.0);
     }
     catch (Exception e)
     {
         System.out.println ("Starting or arrival node does not exists" + e);
     }

     g.Dijkstra ("V1");
     assertArrayEquals (new double[][]{{Graph.INFINITE, 3.0, 4.0, 12.0, 7.0, 10.0}}, g.getD());
     assertArrayEquals (new int[]{-1, 0, 0, 5, 2, 4}, g.getPD());

我想我發現了問題。 您在 initDijkstra 方法中有一個名為 initializeVisitedToFalseExceptStart(departureNode) 的方法。 因此,當在 while 循環中完成對 chooseMinimum 的初始調用時,您將在不考慮離開節點的情況下找到最小值

我認為如果您將在 initDijkstra 方法中刪除該方法調用,您的算法將運行良好。

暫無
暫無

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

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