Golang program to implement dijikstra Algorithm to find shortest path between two nodes in a graph


In this Golang article, we will explore how to implement Dijkstra's Algorithm to find the shortest path between two nodes in a graph using an Adjacency Matrix as well as using an Adjacency List. Dijkstra's Algorithm is used to solve the single-source shortest path problem in a graph with non-negative edge weights.

Algorithm

  • Step 1 − First, we need to import the fmt and math packages. Then create a dist array of length n (the number of nodes in the graph) and initialize it with math.MaxInt32. This array will store the shortest distance from the starting node to every other node in the graph.

  • Step 2 − Then create a function named dijikastra that accepts the graph and two integers as arguments.

  • Step 3 − Inside the function create a visited array of length n and initialize it with false. This array will keep track of which nodes have already been visited.

  • Step 4 − Set dist[start] to 0, where start is the index of the starting node. Repeat the following n-1 times.

  • Step 5 − Find the node u that has not been visited yet and has the shortest distance to the starting node (i.e., dist[u] is the minimum among all nodes that have not been visited yet). Mark u as visited.

  • Step 6 − For each neighbor v of u, if dist[u] + graph[u][v] is less than the current dist[v], update dist[v] to dist[u] + graph[u][v]. Then return the dist array.

  • Step 7 − Here, graph is the adjacency matrix of the graph, where graph[i][j] represents the weight of the edge from node i to node j. If there is no edge between nodes i and j, graph[i][j] should be 0.

Example 1

An adjacency matrix is a 2D array used to represent a graph where the rows and columns represent the vertices, and the values represent the weights of the edges between them. To implement Dijkstra's Algorithm using an adjacency matrix, we can create a 2D array then initialize the distances to infinity, and then iterate over the vertices.

package main

import (
   "fmt"
   "math"
)

func dijkstra(graph [][]int, start int, end int) []int {
   n := len(graph)
   dist := make([]int, n)
   visited := make([]bool, n)

   for i := 0; i < n; i++ {
      dist[i] = math.MaxInt32
      visited[i] = false
   }

   dist[start] = 0

   for count := 0; count < n-1; count++ {
      u := -1

      for i := 0; i < n; i++ {
         if !visited[i] && (u == -1 || dist[i] < dist[u]) {
            u = i
         }
      }

      if u == -1 {
         break
      }

      visited[u] = true

      for v := 0; v < n; v++ {
         if graph[u][v] != 0 && dist[u]+graph[u][v] < dist[v] {
            dist[v] = dist[u] + graph[u][v]
         }
      }
   }

   return dist
}

func main() {
   graph := [][]int{
      {0, 5, 0, 9, 0},
      {5, 0, 2, 0, 0},
      {0, 2, 0, 3, 7},
      {9, 0, 3, 0, 0},
      {0, 0, 7, 0, 0},
   }
   fmt.Println("The given nodes are:", graph)
   start := 0
   end := 4

   dist := dijkstra(graph, start, end)

   fmt.Printf("Shortest path from node %d to %d: %d\n", start, end, dist[end])
}

Output

The given nodes are: [[0 5 0 9 0] [5 0 2 0 0] [0 2 0 3 7] [9 0 3 0 0] [0 0 7 0 0]]
Shortest path from node 0 to 4: 14

Example 2

An adjacency list is a data structure used to represent a graph where each vertex is associated with a list of its neighboring vertices. To implement Dijkstra's Algorithm using an adjacency list, we can create a map where the keys are the vertices and the values are slices of their neighboring vertices and their weights.

package main

import (
   "container/heap"
   "fmt"
   "math"
)

type node struct {
   index int
   dist  int
}

type priorityQueue []*node

func (pq priorityQueue) Len() int {
   return len(pq)
}

func (pq priorityQueue) Less(i, j int) bool {
   return pq[i].dist < pq[j].dist
}

func (pq priorityQueue) Swap(i, j int) {
   pq[i], pq[j] = pq[j], pq[i]
}

func (pq *priorityQueue) Push(x interface{}) {
   *pq = append(*pq, x.(*node))
}

func (pq *priorityQueue) Pop() interface{} {
   old := *pq
   n := len(old)
   x := old[n-1]
   *pq = old[0 : n-1]
   return x
}

func dijkstra(graph [][]node, start int, end int) []int {
   n := len(graph)
   dist := make([]int, n)
   visited := make([]bool, n)

   for i := 0; i < n; i++ {
      dist[i] = math.MaxInt32
      visited[i] = false
   }

   dist[start] = 0

   pq := make(priorityQueue, 0)
   heap.Push(&pq, &node{start, 0})

   for pq.Len() > 0 {
      u := heap.Pop(&pq).(*node)

      if visited[u.index] {
         continue
      }

      visited[u.index] = true

      for _, v := range graph[u.index] {
         if !visited[v.index] && dist[u.index]+v.dist < dist[v.index] {
            dist[v.index] = dist[u.index] + v.dist
            heap.Push(&pq, &node{v.index, dist[v.index]})
         }
      }
   }

   return dist
}

func main() {
   graph := [][]node{
      {{1, 5}, {3, 9}},
      {{0, 5}, {2, 2}},
      {{1, 2}, {3, 3}, {4, 7}},
      {{0, 9}, {2, 3}},
      {{2, 7}},
   }
   fmt.Println("The given nodes are:", graph)
   start := 0
   end := 4
   dist := dijkstra(graph, start, end)
   fmt.Printf("Shortest path from node %d to %d: %d\n", start, end, dist[end])
}

Output

The given nodes are: [[{1 5} {3 9}] [{0 5} {2 2}] [{1 2} {3 3} {4 7}] [{0 9} {2 3}] [{2 7}]]
Shortest path from node 0 to 4: 14

Conclusion

In this article, we explored how to implement Dijkstra's Algorithm in Go to find the shortest path between two nodes in a graph using two different methods: an adjacency matrix and an adjacency list. Both methods work well and have their own advantages and disadvantages. The adjacency matrix method is simple and easy to implement, but it requires more space for larger graphs. The adjacency list method is more space-efficient and can handle larger graphs, but it requires more time to traverse the neighbors of each vertex.

Updated on: 05-Apr-2023

701 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements