简体   繁体   English

Dijkstra 算法自身的实现问题

[英]Dijkstra´s algorithm own implementation problem

I have inside a simple Graph class this Dijkstra Algorithm O(n^2) implementation and when debugging it the output is different than the expected one from the JUnit Test and I cannot find the 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;
            }
        }
    }
}

This is the auxiliary method chooseMinimum():这是辅助方法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;
}

And this is the findOnV_S() method:这是 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;
}

This is the initDijkstra() method:这是 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);
}

And this is the initializeVisitedToFalseExceptStart aux method:这是 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: I think that the wrong method is chooseMinimum() PD:我认为错误的方法是chooseMinimum()

PD2: In the next JUnit you will see that getD() will return a 2 dimensional array but the actual D inside the Graph class is a unidimensional array. PD2:在下一个 JUnit 中,您将看到 getD() 将返回一个二维数组,但 Graph 类中的实际 D 是一个一维数组。

PD3: This is the simple JUnit test: 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());

I think I found the problem.我想我发现了问题。 You have this method called initializeVisitedToFalseExceptStart(departureNode) inside your initDijkstra method.您在 initDijkstra 方法中有一个名为 initializeVisitedToFalseExceptStart(departureNode) 的方法。 So when the initial call to chooseMinimum is done in the while loop, you are finding the minimum without considering the departureNode因此,当在 while 循环中完成对 chooseMinimum 的初始调用时,您将在不考虑离开节点的情况下找到最小值

I think if you will remove that method call inside the initDijkstra method, your algorithm will run fine.我认为如果您将在 initDijkstra 方法中删除该方法调用,您的算法将运行良好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM