简体   繁体   中英

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:

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

    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:

    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:

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:

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

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.

PD3: This is the simple JUnit test:

     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. So when the initial call to chooseMinimum is done in the while loop, you are finding the minimum without considering the departureNode

I think if you will remove that method call inside the initDijkstra method, your algorithm will run fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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