Aaron Li

Algorithm: Graph - Dijkstra's Algorithm

Given a graph and a source vertex in the graph, find the shortest paths from the source to all vertices in the given graph.


notion:  v --- (dis) --- v

               (8)         (7)
        2   ------  3   -------   4
      / |           | \           | \
  (4)/  |       (2) |   \         |  \  (9)
    /   |(11)       |     \  (14) |   \
  1     |      ---- 9       \     |    5
   \    |    /      |        \    |    /
(8) \   |  /(7)     |(6)  (4) \   |   / (10)
     \  | /         |           \ | /
       8 ---------  7   -------- 6      
           (1)            (2)

Start: 1

step1: create records

           1    2    3     4     5     6     7     8    9   
visited    T    F    F     F     F     F     F     F    F
cost       0    4   INF   INF   INF   INF   INF    8   INF 
from       1    1    1     1     1     1     1     1    1 

step2: find the unvisited vertex which has min cost

vertex 2

step3: update distance value of all adjacent vertices of vertex 2

matrix[from][to] = dict

3: 
    record[3] = record[2] + matrix[2][3] = 4 + 8 = 12
    12 < INF => update

8:
    record[8] = record[2] + matrix[2][8] = 4 + 11 = 15
    15 > 8 => do nothing

           1    2    3     4     5     6     7     8    9   
visited    T    T    F     F     F     F     F     F    F
cost       0    4    12   INF   INF   INF   INF    8   INF 
from       1    1    1     1     1     1     1     1    1 

loop step2, 3 till all vertex are visited
type Record struct {
   visited bool
   cost    int
   from    int
}

func Dijkstra(matrix [][]int, start int) []Record {
   num := len(matrix[0])
   records := make([]Record, num)
   for i := 0; i < num; i++ {
   	records[i] = Record{
   		visited: i == start,
   		cost:    matrix[start][i],
   		from:    start,
   	}
   }

   for {
   	nextNode, ok := next(records)

   	if !ok {
   		break
   	}
   	records[nextNode].visited = true

   	for i := 0; i < num; i++ {
   		cost := sum(records[nextNode].cost, matrix[nextNode][i])

   		if cost < records[i].cost {
   			records[i].cost = cost
   			records[i].from = nextNode
   		}
   	}
   }

   return records
}

func next(records []Record) (int, bool) {
   nextNode := -1
   min := math.MaxInt
   for i := 0; i < len(records); i++ {
   	if !records[i].visited && records[i].cost < min {
   		min = records[i].cost
   		nextNode = i
   	}
   }

   return nextNode, nextNode != -1
}

func sum(a int, b int) int {
   // prevent overflow
   if a == math.MaxInt || b == math.MaxInt {
   	return math.MaxInt
   }

   return a + b
}