Golang program to find minimum spanning tree using dijkstra Algorithm


In this article we will write a go language program to find minimum spanning of tree. A minimum spanning tree (MST) is a tree that connects all the nodes in an undirected, weighted graph with the minimum possible edges. There are several Algorithms to find the minimum spanning tree of a graph like dijkastra Algorithm, prim's Algorithm and kruskal's Algorithm.

What is Dijkistra Algorithm?

Dijkstra's Algorithm is an Algorithm that finds the shortest path between a source vertex and all other vertices in a weighted graph with non-negative edge weights. It works by maintaining a set of visited vertices and a set of unvisited vertices, and keeping track of the minimum distance from the source vertex to each vertex in the graph.

Algorithm

  • Step 1 − First, we need to import the fmt and math package. Then define a struct node. Initialize the distance and visited arrays.

  • Step 2 − Set the distance of the source vertex to 0 and push it into the priority queue.

  • Step 3 − While the priority queue is not empty, extract the vertex with the minimum distance from the queue.

  • Step 4 − Mark the extracted vertex as visited and for each of its neighbors, update their distances if a shorter path is found.

  • Step 5 − Push each updated neighbor into the priority queue if it is not visited yet. Return the minimum spanning tree.

  • Step 6 − Now, create the main() function. Inside the main() initialize the nodes of the graph and print them on the screen.

  • Step 7 − Now, call the findMst() function by passing the above node as argument to it and store the result in a variable.

  • Step 8 − Further, print the result on the screen.

Example 1

In this Example we will discuss is using a priority queue to implement Dijkstra's Algorithm. The basic idea of this method is to keep track of the minimum distance from the source node to each node in the graph. We will also keep track of the previous node in the shortest path from the source node to each node.

package main

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

type Node struct {
   id   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{}) {
   node := x.(*Node)
   *pq = append(*pq, node)
}

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

func findMST(graph [][]int, source int) [][]int {
   n := len(graph)
   dist := make([]int, n)
   prev := make([]int, n)
   visited := make([]bool, n)

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

   dist[source] = 0
   pq := &PriorityQueue{}
   heap.Init(pq)
   heap.Push(pq, &Node{id: source, dist: 0})

   for pq.Len() > 0 {
      node := heap.Pop(pq).(*Node)
      id := node.id

      if visited[id] {
         continue
      }

      visited[id] = true

      for j := 0; j < n; j++ {
         if graph[id][j] != 0 && !visited[j] {
            alt := dist[id] + graph[id][j]
            if alt < dist[j] {
               dist[j] = alt
               prev[j] = id
               heap.Push(pq, &Node{id: j, dist: alt})
            }
         }
      }
   }

   mst := make([][]int, n)

   for i := 0; i < n; i++ {
      mst[i] = make([]int, n)
   }

   for i := 0; i < n; i++ {
      if prev[i] != i {
         mst[prev[i]][i] = graph[prev[i]][i]
         mst[i][prev[i]] = graph[prev[i]][i]
      }
   }
   return mst
}

func main() {
   graph := [][]int{
      {0, 2, 0, 6, 0},
      {2, 0, 3, 8, 5},
      {0, 3, 0, 0, 7},
      {6, 8, 0, 0, 9},
      {0, 5, 7, 9, 0},
   }
   fmt.Println("The given nodes are:", graph)
   mst := findMST(graph, 0)
   fmt.Println()
   fmt.Println("Minimum Spanning Tree:")
   for _, row := range mst {
      fmt.Println(row)
   }
}

Output

The given nodes are: [[0 2 0 6 0] [2 0 3 8 5] [0 3 0 0 7] [6 8 0 0 9] [0 5 7 9 0]]

Minimum Spanning Tree:
[0 2 0 6 0]
[2 0 3 0 5]
[0 3 0 0 0]
[6 0 0 0 0]
[0 5 0 0 0]

Example 2

In second Example we will discuss is using a heap to implement Dijkstra's Algorithm. The basic idea of this method is similar to the first method, but instead of using a priority queue, we will use a heap to store the nodes in the order of their distance from the source node.

package main

import (
   "fmt"
   "math"
)

type Node struct {
   id   int
   dist int
}

type Heap []*Node

func (h Heap) Len() int           { return len(h) }
func (h Heap) Less(i, j int) bool { return h[i].dist < h[j].dist }
func (h Heap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *Heap) Push(x interface{}) {
   node := x.(*Node)
   *h = append(*h, node)
}

func (h *Heap) Pop() interface{} {
   old := *h
   n := len(old)
   node := old[n-1]
   *h = old[0 : n-1]
   return node
}

func findMST(graph [][]int, source int) [][]int {
   n := len(graph)
   dist := make([]int, n)
   prev := make([]int, n)
   visited := make([]bool, n)

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

   dist[source] = 0
   heap := &Heap{}
   heap.Push(&Node{id: source, dist: 0})

   for heap.Len() > 0 {
      node := heap.Pop().(*Node)
      id := node.id

      if visited[id] {
         continue
      }

      visited[id] = true

      for j := 0; j < n; j++ {
         if graph[id][j] != 0 && !visited[j] {
            alt := dist[id] + graph[id][j]

            if alt < dist[j] {
               dist[j] = alt
               prev[j] = id
               heap.Push(&Node{id: j, dist: alt})
            }
         }
      }
   }

   mst := make([][]int, n)

   for i := 0; i < n; i++ {
      mst[i] = make([]int, n)
   }

   for i := 0; i < n; i++ {
      if prev[i] != i {
         mst[prev[i]][i] = graph[prev[i]][i]
         mst[i][prev[i]] = graph[prev[i]][i]
      }
   }
   return mst
}

func main() {
   // Example graph
   graph := [][]int{
      {0, 2, 0, 6, 0},
      {2, 0, 3, 8, 5},
      {0, 3, 0, 0, 7},
      {6, 8, 0, 0, 9},
      {0, 5, 7, 9, 0},
   }

   // Find minimum spanning tree
   mst := findMST(graph, 0)
   fmt.Println("The given nodes of the graph are:", mst)
   fmt.Println()
   
   // Print minimum spanning tree
   fmt.Println("Minimum spanning tree is:")
   for _, row := range mst {
      fmt.Println(row)
   }
}

Output

The given nodes of the graph are: [[0 2 0 6 0] [2 0 0 0 0] [0 0 0 0 7] [6 0 0 0 9] [0 0 7 9 0]]

Minimum spanning tree is:
[0 2 0 6 0]
[2 0 0 0 0]
[0 0 0 0 7]
[6 0 0 0 9]
[0 0 7 9 0]

Conclusion

We have discussed three methods to implement Dijkstra's Algorithm to find the minimum spanning tree of a graph in Golang. All these methods are efficient and have similar time complexities, but using a priority queue or a heap can be more efficient than using an array. The choice of method depends on the specific requirements of the problem at hand.

Updated on: 05-Apr-2023

356 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements