dijkstra算法

149 阅读2分钟

dijkstra算法,最经典的单源最短路径算法

以下面的有向加权图分析dijkstra算法

image.png

S=[0]

D(0)=0 D(1)=600 D(2)=900 D(3)=200 D(4)=1100 D(5)=D(6)= D(6)= D(7)=$

S=[0、3]

D(0)=0 D(1)=600 D(2)=800 D(3)=200 D(4)=1100 D(5)=D(6)= D(6)= D(7)=1700

S=[0、3、1]

D(0)=0 D(1)=600 D(2)=800 D(3)=200 D(4)=1000 D(5)=800 D(6)=$ D(7)=1700

S=[0、3、1、2]

D(0)=0 D(1)=600 D(2)=800 D(3)=200 D(4)=1000 D(5)=800 D(6)=1300 D(7)=1700

S=[0、3、1、2、5]

D(0)=0 D(1)=600 D(2)=800 D(3)=200 D(4)=1000 D(5)=800 D(6)=1200 D(7)=1700

S=[0、3、1、2、5、4]

D(0)=0 D(1)=600 D(2)=800 D(3)=200 D(4)=1000 D(5)=800 D(6)=1200 D(7)=1700

S=[0、3、1、2、5、4、6、7]

D(0)=0 D(1)=600 D(2)=800 D(3)=200 D(4)=1000 D(5)=800 D(6)=1200 D(7)=1700

代码实现

const MaxDistance = math.MaxInt32

func dijkstra(i int, j int, n int, weight []int, edges [][]int) int {
   s := make(map[int]int, 0)
   distance := make(map[int]int, 0)
   for k := 0; k < n; k++ {
      if k == i {
         distance[k] = 0
      } else {
         distance[k] = math.MaxInt32
      }
   }

   outCome := make(map[int]map[int]int, 0)
   for k, edge := range edges {
      u, v := edge[0], edge[1]
      if _, ok := outCome[u]; !ok {
         outCome[u] = make(map[int]int, 0)
      }
      outCome[u][v] = weight[k]

      if u == i {
         distance[v] = weight[k]
      }
   }

   fmt.Println("s:", s)
   fmt.Println("distance:", distance)
   fmt.Println("outCome:", outCome)

   minDistance := func() (int, int) {
      v := -1
      min := MaxDistance
      for i, d := range distance {
         if _, ok := s[i]; !ok && d < min {
            min = d
            v = i
         }
      }
      return v, min
   }

   for len(outCome) > 0 {
      v, min := minDistance() //v=3 min=200
      if v < 0 {
         return -1
      }
      s[v] = 0 //s = [0:0, 3:0]

      tmp := outCome[v] // tmp = [2:600, 7:1500]
      for key, val := range tmp {
         //200 + 600 < 900
         if min+val < distance[key] {
            distance[key] = min + val
         }
      }
      delete(outCome, v)
   }
   fmt.Println("-----------------------------")
   fmt.Println(s)
   fmt.Println(distance)
   fmt.Println(outCome)

   return distance[j]
}

func main() {
   edges := [][]int{[]int{0, 1}, []int{0, 2}, []int{0, 3}, []int{0, 4}, []int{1, 2}, []int{1, 4}, []int{1, 5}, []int{2, 1}, []int{2, 6}, []int{2, 7}, []int{3, 2}, []int{3, 7}, []int{4, 5}, []int{5, 6}, []int{6, 1}}
   weight := []int{600, 900, 200, 1100, 500, 400, 200, 400, 500, 1400, 600, 1500, 400, 300, 200}
   fmt.Println(dijkstra(0, 7, 8, weight, edges))
}

原理简单来说就是一条最短路径上的任意节点到原点的距离都是最短的。所以每次只用找到最短路径节点并延伸即可。

参考文章:

zhuanlan.zhihu.com/p/40338107

juejin.cn/post/684490…