Dijkstra’s Algorithm

In Computer Science, a common problem that we encounter are parthfinding problems. These problems are typically seen in GPS programs, maze-solvers, or robotics. We would typically represent the map in queston with a graph. For the sake of demonstrating Dijkstra’s algorithm, we will implement our own weighted graphs to use for this algorithm

Weighted Graph

To implement our weighted graph, we could create a Node() object representing each individual vertice, and the weighted edges that it is connected by. This Node object should have the following properties:

  • Store the label of the Vertice at question
  • Store a hashmap of edges that points to other nodes, associated with a numerical value (Integer:Integer)
  • Grab the label and edges
  • Update the label and edges
  • Add an edge to a node connecting it to an adjacent node. Additionally, our WeightedGraph() object should support opperations to create a shared edge beween two nodes, such that our graph is always bi-directional.
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.Stack;
public class Node {
    private int VerticeIndex;
    private HashMap<Integer, Integer> Edges;

    Node (int ProvidedIndexFromFrontend) {
        this.VerticeIndex = ProvidedIndexFromFrontend; 
        this.Edges = new HashMap<Integer, Integer>();
    }

    Node (int ProvidedIndexFromFrontend, HashMap<Integer, Integer> ProvidedEdgesFromFrontend) {
        this.VerticeIndex = ProvidedIndexFromFrontend; 
        this.Edges = ProvidedEdgesFromFrontend;
    }

    public int getIndex() {
        return this.VerticeIndex;
    }

    public HashMap<Integer, Integer> getEdges() {
        return this.Edges;
    }

    public void setIndex(int ProvidedIndex) {
        this.VerticeIndex = ProvidedIndex;
    }

    public void addEdgeToVertex(int ProvidedDestinationIndex, int ProvidedEdgeWeight) {
        this.Edges.put(ProvidedDestinationIndex, ProvidedEdgeWeight);
    }

    public void removeEdgeFromVertex(int ProvidedDestinationIndex) {
        this.Edges.remove(ProvidedDestinationIndex);
    }

    public int getDistanceBetweenTwoVertices(Node ProvidedDestinationVerticeNode) {
        return this.Edges.get(ProvidedDestinationVerticeNode.getIndex());
    }

    public ArrayList<Integer> getNeighborsOfVertice() {
        ArrayList<Integer> ListOfEdges = new ArrayList<Integer>();
        for ( int VerticeKey : this.Edges.keySet()) {
            ListOfEdges.add(VerticeKey);
        }
        return ListOfEdges;
    }
}
public class BiDirectionalWeightedGraph {
    private ArrayList<Node> Graph;

    BiDirectionalWeightedGraph() {
        this.Graph = new ArrayList<Node>();
    }
    
    public ArrayList<Node> retrieveGraph(){
        return this.Graph;
    }

    private int getMaximumLabel() {
        return this.Graph.size();
    }

    private boolean isVerticeExist(int ProvidedLabel) {
        for (Node vertice : this.Graph) {
            if (vertice.getIndex() == ProvidedLabel) {
                return true;
            }
        }
        return false;
    }

    public void addVertice(Node ProvidedNewVertice) {
        for (Node vertice : this.Graph) {
            if (vertice.getIndex() == ProvidedNewVertice.getIndex()) {
                return ;
            }
        }
        this.Graph.add(ProvidedNewVertice);
    }

    public Node getVerticeFromLabel(int ProvidedLabel) {
        for (Node vertice : this.Graph) {
            if (vertice.getIndex() == ProvidedLabel) {
                return vertice;
            }
        }
        return null;
    }

    public void addEdgeToGraph(int ProvidedSourceVertice, int ProvidedDestinationVertice, int ProvidedEdgeWeight) {
        assert isVerticeExist(ProvidedSourceVertice);
        assert isVerticeExist(ProvidedDestinationVertice);
        Node SourceVerticeObj = getVerticeFromLabel(ProvidedSourceVertice);
        Node DestinationVerticeObj = getVerticeFromLabel(ProvidedDestinationVertice);
        SourceVerticeObj.addEdgeToVertex(ProvidedDestinationVertice, ProvidedEdgeWeight);   
        DestinationVerticeObj.addEdgeToVertex(ProvidedSourceVertice, ProvidedEdgeWeight);       
    }

    public void removeEdgeFromGraph(int ProvidedSourceVertice, int ProvidedDestinationVertice, int ProvidedEdgeWeight) {
        assert isVerticeExist(ProvidedSourceVertice);
        assert isVerticeExist(ProvidedDestinationVertice);
        Node SourceVerticeObj = getVerticeFromLabel(ProvidedSourceVertice);
        Node DestinationVerticeObj = getVerticeFromLabel(ProvidedDestinationVertice);
        SourceVerticeObj.removeEdgeFromVertex(ProvidedDestinationVertice);   
        DestinationVerticeObj.removeEdgeFromVertex(ProvidedSourceVertice);       
    }

    public int[][] getAdjacencyList() {
        int adjacencyList[][] = new int[Graph.size()+1][Graph.size()+1];
        for (Node vertice : Graph) {
            int source = vertice.getIndex();
            adjacencyList[0][source]=source;
            adjacencyList[source][0]=source;
            for (Map.Entry<Integer, Integer> entry : vertice.getEdges().entrySet()) {
                int destination = entry.getKey();
                int weight = entry.getValue();
                adjacencyList[source][destination] = weight;
            }
        }
        return adjacencyList;
    }
}

BiDirectionalWeightedGraph test = new BiDirectionalWeightedGraph();

Node vertice1 = new Node(1);
Node vertice2 = new Node(2);
Node vertice3 = new Node(3);
Node vertice4 = new Node(4);
Node vertice5 = new Node(5);
Node vertice6 = new Node(6);
Node vertice7 = new Node(7);
Node vertice8 = new Node(8);
Node vertice9 = new Node(9);
Node vertice10 = new Node(10);
Node vertice11 = new Node(11);


test.addVertice(vertice1);
test.addVertice(vertice2);
test.addVertice(vertice3);
test.addVertice(vertice4);
test.addVertice(vertice5);
test.addVertice(vertice6);
test.addVertice(vertice7);
test.addVertice(vertice8);
test.addVertice(vertice9);
test.addVertice(vertice10);
test.addVertice(vertice11);

test.addEdgeToGraph(10, 1, 50);
test.addEdgeToGraph(1, 2, 3);
test.addEdgeToGraph(2, 3, 2);
test.addEdgeToGraph(3, 4, 7);
test.addEdgeToGraph(4, 5, 1);
test.addEdgeToGraph(5, 6, 4);
test.addEdgeToGraph(6, 7, 6);
test.addEdgeToGraph(7, 8, 8);
test.addEdgeToGraph(8, 9, 9);
test.addEdgeToGraph(9, 10, 1000);
test.addEdgeToGraph(10, 2, 40);
test.addEdgeToGraph(2, 4, 6);
test.addEdgeToGraph(4, 6, 8);
test.addEdgeToGraph(6, 8, 10);
test.addEdgeToGraph(8, 10, 20000);
test.addEdgeToGraph(1, 3, 6);
test.addEdgeToGraph(3, 5, 8);
test.addEdgeToGraph(5, 7, 10);
test.addEdgeToGraph(7, 9, 2);


ArrayList<Node> sampleList = test.retrieveGraph();
for (Node node: sampleList) {
    System.out.println(node.getIndex() + " : " + node.getEdges());
}

System.out.println(sampleList.size());
int sampleAdjacencyList[][] = test.getAdjacencyList();
for (int i = 0; i < sampleAdjacencyList.length; i++ ) {
    for (int j = 0; j < sampleAdjacencyList.length; j++ ) {
        System.out.print(sampleAdjacencyList[i][j] + " ");
    }
    System.out.println();
}
1 : {2=3, 3=6, 10=50}
2 : {1=3, 3=2, 4=6, 10=40}
3 : {1=6, 2=2, 4=7, 5=8}
4 : {2=6, 3=7, 5=1, 6=8}
5 : {3=8, 4=1, 6=4, 7=10}
6 : {4=8, 5=4, 7=6, 8=10}
7 : {5=10, 6=6, 8=8, 9=2}
8 : {6=10, 7=8, 9=9, 10=20000}
9 : {7=2, 8=9, 10=1000}
10 : {1=50, 2=40, 8=20000, 9=1000}
11 : {}
11
0 1 2 3 4 5 6 7 8 9 10 11 
1 0 3 6 0 0 0 0 0 0 50 0 
2 3 0 2 6 0 0 0 0 0 40 0 
3 6 2 0 7 8 0 0 0 0 0 0 
4 0 6 7 0 1 8 0 0 0 0 0 
5 0 0 8 1 0 4 10 0 0 0 0 
6 0 0 0 8 4 0 6 10 0 0 0 
7 0 0 0 0 10 6 0 8 2 0 0 
8 0 0 0 0 0 10 8 0 9 20000 0 
9 0 0 0 0 0 0 2 9 0 1000 0 
10 50 40 0 0 0 0 0 20000 1000 0 0 
11 0 0 0 0 0 0 0 0 0 0 0 

Dijkstra methods

public class DijkstraAlgorithm {
    private static final int inf = Integer.MAX_VALUE;
    private static HashMap<Node, Integer> ShortestDistanceMap;
    private static HashMap<Integer, Integer> ParentVerticesMap;
    private static ArrayList<Node> NodeArrayList;
    private static Node CurrentNodeToTraverse;
    private static int alt;
    private static BiDirectionalWeightedGraph InputGraph;
    
    
    public static HashMap<Node, Integer> dijkstra(BiDirectionalWeightedGraph Graph, int SourceVertexLabel) {
        InputGraph = Graph;
        ShortestDistanceMap = new HashMap<Node, Integer>();
        ParentVerticesMap = new HashMap<Integer, Integer>();
        NodeArrayList = new ArrayList<Node>();
        Node SourceVertextNodeObject = InputGraph.getVerticeFromLabel(SourceVertexLabel);
        Node CurrentNodeToTraverse;
        for (Node vertice : InputGraph.retrieveGraph()) {
            ShortestDistanceMap.put(vertice, inf-1);
            ParentVerticesMap.put(vertice.getIndex(), null);
            NodeArrayList.add(vertice);
        }

        ShortestDistanceMap.put(SourceVertextNodeObject, 0);

        while (NodeArrayList.size() != 0) {
            CurrentNodeToTraverse = FindMinDistInNodesArrayList();
            NodeArrayList.remove(CurrentNodeToTraverse);

            for (int verticeLabel : CurrentNodeToTraverse.getNeighborsOfVertice()) {
                Node vertice = InputGraph.getVerticeFromLabel(verticeLabel);
                if (NodeArrayList.contains(vertice)) {
                    alt = ShortestDistanceMap.get(CurrentNodeToTraverse) + vertice.getDistanceBetweenTwoVertices(CurrentNodeToTraverse);
                    if (alt < ShortestDistanceMap.get(vertice)) {
                        ShortestDistanceMap.put(vertice, alt);
                        ParentVerticesMap.put(vertice.getIndex(), CurrentNodeToTraverse.getIndex());
                    }
                }
            } 
        }
        return ShortestDistanceMap;
    }

    private static Node FindMinDistInNodesArrayList () {
        int minimumDistance = inf; 
        int newDistance;
        Node optimalNode = null;
        for (Node vertice : NodeArrayList) {
            newDistance = ShortestDistanceMap.get(vertice);
            if (newDistance < minimumDistance) {
                minimumDistance = newDistance;
                optimalNode = vertice;
            }
        }
        return optimalNode;
    }

    public static Stack<Integer> ReverseIteratePath (int sourceNodetoIterate, int targetNodetoIterate) {
        Stack<Integer> ShortestPathStack = new Stack<Integer>();
        System.out.println(ParentVerticesMap.get(targetNodetoIterate));
        Integer CurrentNodeToTrace = targetNodetoIterate;
        if (ParentVerticesMap.get(CurrentNodeToTrace)!=null || CurrentNodeToTrace == sourceNodetoIterate) {
            System.out.println("HELLLLLLLLLO IF THIS RUNS I THINK JAVA IS BROKEN");
            while (CurrentNodeToTrace!=null) {
                ShortestPathStack.push(CurrentNodeToTrace);
                CurrentNodeToTrace = ParentVerticesMap.get(CurrentNodeToTrace);
            }
        }
        return ShortestPathStack;
    }

    public static void main(String args[]) {
        dijkstra(test, 9);
        for (Map.Entry<Node, Integer> optimalDistance : ShortestDistanceMap.entrySet()) {
            System.out.println("Shortest distance from vertex 9 to vertex " + 
            optimalDistance.getKey().getIndex() + 
            " is: " 
            + optimalDistance.getValue());
        }
        Stack<Integer> OptimalDistanceToTarget = ReverseIteratePath(9, 10);
        System.out.println(OptimalDistanceToTarget);
        while (!OptimalDistanceToTarget.isEmpty()) {
            System.out.println(OptimalDistanceToTarget.pop());
        }
    }

}
DijkstraAlgorithm.main(null);
Shortest distance from vertex 9 to vertex 2 is: 19
Shortest distance from vertex 9 to vertex 3 is: 20
Shortest distance from vertex 9 to vertex 4 is: 13
Shortest distance from vertex 9 to vertex 5 is: 12
Shortest distance from vertex 9 to vertex 8 is: 9
Shortest distance from vertex 9 to vertex 7 is: 2
Shortest distance from vertex 9 to vertex 10 is: 59
Shortest distance from vertex 9 to vertex 1 is: 22
Shortest distance from vertex 9 to vertex 6 is: 8
Shortest distance from vertex 9 to vertex 11 is: 2147483646
Shortest distance from vertex 9 to vertex 9 is: 0
2
HELLLLLLLLLO IF THIS RUNS I THINK JAVA IS BROKEN
[10, 2, 4, 5, 7, 9]
9
7
5
4
2
10