Categories
Data Structure & Algorithm
Hello, today’s discussion is about Dijkstra’s Algorithm. Let me start by saying that so far in the graph section we’ve been dealing with a graph with no real data but only vertices, this is what we call an unweighted Graph a graph which has only vertices and edges without any indication as to what those edges carry, but here in Dijkstra’s Algorithm we’re going to talk about a graph which has real data indication. A weighted graph as opposed to the unweighted graphs. So what’s Dijkstra’s Algorithm.
Dijkstra’s Algorithm: Is an algorithm that finds the shortest distance between vertices in a graph structure and in fact this is one of the most spoken about algorithms in computer science, Dijkstra himself was a very dedicated German Computer scientist who contributed greatly to the world of computer science , kind of a God Father if you may put it that way. He invented this algorithm to calculate the shortest distance from a city to another another one given various routes. this simple invention is seen implemented in most industries up till date, talking of Computer Networking, Road Networking, Airlines Protocols, Biology etc… you can read more about this man on Wikipedia he made many publications in his life time. he wrote about different subjects in Computer science and other Areas like physics
 So Dijkstra’s Algorithms says that from a starting point there should be a shortest distance to reach another point even if there is not direct route leading these two points but through one the other can be reached and there should be a much better route to take and reach there, all we need to do is to visit them (Vertex) and compute the previous distance with the current cost of reaching the new vertex as we update the end point(Unknown) with the result of our computation. Here are the needed parameters to get the job done.

Let’s say from a A to D through B and C we want to find the shortest distance to get from A to D, Assuming those points are not in line but spread on different routes, Dijkstra’s Algorithm says that Move from the starting point ie. A and look for the shortest distance between the adjacent vertex and visit it first then since the destination is unknown use the current total distance and add to the cost of moving from the second current point to the destination and at arrival compute all and donate it to the destination as the total distance taken, repeat for all the routes that leads to the other side and compare all rounds to deduce the shortest distance. seems little abstract right ? let’s see what we mean below. the needed pre-requisite for this task are a Definition of a node, a priority queue and a weighted graph to find the Dijkstra’s Algorithms. Since we had a look at almost all those processes am going to bring back the same codes we covered earlier and chain it with the Dijkstra’s in the weighted graph.

 



class Node {
  constructor(val, priority) {
    this.val = val;
    this.priority = priority;
  }
}
class PriorityQueue {
  constructor() {
    this.values = [];
  }
  enqueue(val, priority) {
    let newNode = new Node(val, priority);
    this.values.push(newNode);
    this.bubbleUp();
  }
  bubbleUp() {
    let idx = this.values.length - 1;
    const element = this.values[idx];
    while (idx > 0) {
      let parentIdx = Math.floor((idx - 1) / 2);
      let parent = this.values[parentIdx];
      if (element.priority >= parent.priority) break;
      this.values[parentIdx] = element;
      this.values[idx] = parent;
      idx = parentIdx;
    }
  }
  dequeue() {
    const min = this.values[0];
    const end = this.values.pop();
    if (this.values.length > 0) {
      this.values[0] = end;
      this.sinkDown();
    }
    return min;
  }
  sinkDown() {
    let idx = 0;
    const length = this.values.length;
    const element = this.values[0];
    while (true) {
      let leftChildIdx = 2 * idx + 1;
      let rightChildIdx = 2 * idx + 2;
      let leftChild, rightChild;
      let swap = null;

      if (leftChildIdx < length) {
        leftChild = this.values[leftChildIdx];
        if (leftChild.priority < element.priority) {
          swap = leftChildIdx;
        }
      }
      if (rightChildIdx < length) {
        rightChild = this.values[rightChildIdx];
        if (
          (swap === null && rightChild.priority < element.priority) ||
          (swap !== null && rightChild.priority < leftChild.priority)
        ) {
          swap = rightChildIdx;
        }
      }
      if (swap === null) break;
      this.values[idx] = this.values[swap];
      this.values[swap] = element;
      idx = swap;
    }
  }
}

class WeightedGraph {
  constructor() {
    this.adjacencyList = {};
  }
  addVertex(vertex) {
    if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = [];
  }
  addEdge(vertex1, vertex2, weight) {
    this.adjacencyList[vertex1].push({ node: vertex2, weight });
    this.adjacencyList[vertex2].push({ node: vertex1, weight });
  }
  Dijkstra(start, finish) {
    const nodes = new PriorityQueue();
    const distances = {};
    const previous = {};
    let path = []; //to return at end
    let smallest;
    //build up initial state
    for (let vertex in this.adjacencyList) {
      if (vertex === start) {
        distances[vertex] = 0;
        nodes.enqueue(vertex, 0);
      } else {
        distances[vertex] = Infinity;
        nodes.enqueue(vertex, Infinity);
      }
      previous[vertex] = null;
    }
    // as long as there is something to visit
    while (nodes.values.length) {
      smallest = nodes.dequeue().val;
      if (smallest === finish) {
        //WE ARE DONE
        //BUILD UP PATH TO RETURN AT END
        while (previous[smallest]) {
          path.push(smallest);
          smallest = previous[smallest];
        }
        break;
      }
      if (smallest || distances[smallest] !== Infinity) {
        for (let neighbor in this.adjacencyList[smallest]) {
          //find neighboring node
          let nextNode = this.adjacencyList[smallest][neighbor];
          //calculate new distance to neighboring node
          let candidate = distances[smallest] + nextNode.weight;
          let nextNeighbor = nextNode.node;
          if (candidate < distances[nextNeighbor]) {
            //updating new smallest distance to neighbor
            distances[nextNeighbor] = candidate;
            //updating previous - How we got to neighbor
            previous[nextNeighbor] = smallest;
            //enqueue in priority queue with new priority
            nodes.enqueue(nextNeighbor, candidate);
          }
        }
      }
    }
    return path.concat(smallest).reverse();
  }
}

var graph = new WeightedGraph();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addVertex('D');
graph.addVertex('E');
graph.addVertex('F');
graph.addVertex('G');

graph.addEdge('A', 'B', 4);
graph.addEdge('A', 'C', 2);
graph.addEdge('B', 'E', 3);
graph.addEdge('C', 'D', 2);
graph.addEdge('C', 'F', 4);
graph.addEdge('D', 'E', 3);
graph.addEdge('D', 'F', 1);
graph.addEdge('E', 'F', 1);
graph.addEdge('F', 'G', 1);

graph.Dijkstra('A', 'G');

console.log(graph.Dijkstra('A', 'G'));

 

No cause for alarm here the code is lengthy but we just repeated the same previous section snippets to help figure out how to build the Dijkstra’s Algorithm. kindly take a look at it and try to make some meaning out of it, you’re not supposed to understand it just at once but little efforts of not giving up yet and practicing will help really understand what is really going on in the above solutions. Read more and keep practicing, Next we will look at Dynamic Programming. Stay Safe 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *