【你該懂一點Javascript算法系列】之單源最短路徑 - Dijkstra算法

Javascript算法系列 - 單源最短路徑 - Dijkstra算法

迪傑斯特拉算法是由荷蘭計算機科學家狄克斯特拉於1959
年提出的,所以又叫狄克斯特拉算法。是從一個頂點到其他各頂點的最短路徑算法,解決的是有向圖中最短路徑問題。迪傑斯特拉算法主要特色是以起始點爲中心向外層層擴展,直到擴展到終點爲止

ps: Dijkstra算法是一種貪心算法javascript

clipboard.png

以上圖爲例
咱們要求出頂點A到其他各頂點間的最短路徑

首先咱們先定義出上圖的鄰接矩陣java

let graph = [[0,2,4,0,0,0],
             [0,0,1,4,2,0],
             [0,0,0,0,3,0],
             [0,0,0,0,0,2],
             [0,0,0,3,0,2],
             [0,0,0,0,0,0]]

ps: 鄰接矩陣的意思是: 用一個二數組表示個頂點間的關係,來肯定各頂點間的關係,由於圖爲有向圖,因此上圖的鄰接矩陣如上算法

clipboard.png

先放出Dijkstra算法的所有代碼再來結合慢慢解析數組

let index = 'ABCDEF'
let INF = Number.MAX_SAFE_INTEGER //1

function dijkstra(src) {
  let dist = [],//2
      visited = [],//3
      length = graph.length//4

  for (let i = 0; i < length; i++) {
    dist[i] = INF
    visited[i] = false 
  }//5
  dist[src] = 0

  for (let i = 0; i < length - 1; i++) {
    let u = minDistance(dist, visited)
    visited[u] = true
    
    for (let v = 0; v < length; v++) {
      if (!visited[v] && dist[u] !== INF && graph[u][v] > 0 && dist[u] + graph[u][v] < dist[v]) {
        dist[v] = dist[u] + graph[u][v]
      }
    }
  }

  return dist
}

function minDistance(dist, visited) {
  let min = INF,
      minIndex = -1
  
  for (let v = 0; v < dist.length; v++) {
    if (visited[v] === false && dist[v] <= min) {
      min = dist[v]
      minIndex = v
    }
  }
  
  return minIndex
}

1.初始化數據
定義 dist 數組來儲存當前A頂點到其它各個頂點間的距離
定義 visited 數組來儲存ABCDEF頂點是否被訪問過,以避免重複訪問,造成環
定義 length 來儲存全部頂點的數量
定義 INF 爲javascript的最大整數 Number.MAX_SAFE_INTEGER函數

for (let i = 0; i < length; i++) {
    dist[i] = INF
    visited[i] = false 
  }//5
  dist[src] = 0
初始化dist visted 數組,把全部頂點距離初始化爲無限大,全部頂點定義爲爲訪問
把頂點A到本身的距離初始化爲0

2.過程解析spa

//頂點探索函數
for (let i = 0; i < length - 1; i++) {
    let u = minDistance(dist, visited)
    visited[u] = true
    
    for (let v = 0; v < length; v++) {
      if (!visited[v] && dist[u] !== INF && graph[u][v] > 0 && dist[u] + graph[u][v] < dist[v]) {
        dist[v] = dist[u] + graph[u][v]
      }
    }
  }
//尋找最短路徑函數
function minDistance(dist, visited) {
  let min = INF,
      minIndex = -1
  
  for (let v = 0; v < dist.length; v++) {
    if (visited[v] === false && dist[v] <= min) {
      min = dist[v]
      minIndex = v
    }
  }
  
  return minIndex
}

具體探索邏輯以下code

第一次循環
找到最短頂點A
遍歷A到其餘頂點的距離,若是和其餘頂點有直接聯繫,則判斷A到其餘頂點的距離,是不是A目前到X頂點的距離 + X到新頂點的距離 < A新頂點的距離
若是小於,則更新到該頂點最短距離blog

第一次循環完後相應輸出值
發現A
遍歷發現A -> B爲2 A->C爲4 均小於無窮大,因此更新A點到B,C的最短距離ip

visited -> [ true, false, false, false, false, false ]
dist -> [ 0, 2, 4, 9007199254740991, 9007199254740991, 9007199254740991 ]

第二次循環
找到最短的那個邊,除A之外 因此探索B點
遍歷發現 B->C,B->E, B->D分別爲1,2,4

A-C距離爲A-B + B-C = 3小於直接到C的距離4 因此更新A-C最短距離it

visited -> [ true, true, false, false, false, false ]
dist -> [ 0, 2, 3, 6, 4, 9007199254740991 ]

剩下三次探索輸出爲
dist -> [ 0, 2, 3, 6, 4, 9007199254740991 ]
visited -> [ true, true, true, false, true, false ]
dist -> [ 0, 2, 3, 6, 4, 6 ]
visited -> [ true, true, true, false, true, true ]
[ 0, 2, 3, 6, 4, 6 ]

這樣就會得到A到全部邊的最短距離
[ 0, 2, 3, 6, 4, 6 ]

這就是js實現Dijkstra算法的過程,有些簡短,有問題能夠留言交流

相關文章
相關標籤/搜索