최단 경로 알고리즘의 Dijkstra(Dijkstra 알고리즘) 및 JS 코드 구현 이해

 1. 예시 그림

예 1

        다음 그림에는 4개의 점 ABCD가 있습니다. A에서 각 점까지의 최단 경로를 찾으십시오.

  • 먼저 최종 A에서 각 지점까지의 최단 경로인 레코드(record finally)를 준비합니다. 처음에는 비어 있습니다.
  •  A가 시작점이며 A에서 B, C, D에 직접 도달할 수 있습니다. A에서 B로 가는 경로는 2, C로 가는 경로는 5, D로 가는 경로는 3입니다. "기록 1"은 다음과 같습니다. 다음과 같습니다.
  1. A→B:2
  2. A→C:5
  3. A→D:3

        최단 경로 A→B: 2를 "최종 기록"으로 이동한 다음 "최종 기록"은 A→B: 2

  • 포인트 B는 C로 갈 수 있습니다: B→C: 4, A에서 C로 B에서 전송하도록 선택할 수 있습니다: 이때 A→C: 2+4=6, 6>5, 따라서 "레코드 1"은 업데이트되지 않습니다 ( B→C: 2 라고 가정하고 이때 A→C: 2+2=4, 4<5, "레코드 1" 업데이트: A→C: 4 )
  • 포인트 D는 C로 갈 수 있습니다: D→C: 3, A에서 C로, D에서 전송하도록 선택할 수 있습니다: 이때 A→C: 3+3=6, 6>5이므로 "레코드 1"은 업데이트되지 않음
  • C 지점에 도달 가능한 지점이 없으므로 계산 종료
  • "Record 1"을 "Record finally"로 병합
  • 마지막으로 A에서 각 지점까지의 최단 경로를 얻습니다. A→B: 2, A→C: 5, A→D : 3 →C: 4. A → D: 3)

예 2

        아래 그림과 같이 A에서 각 지점까지의 최단 경로를 찾으십시오.

        인스턴스 1의 레코드는 최종적으로 집합 S로 기록되며 초기 S에는 시작점만 포함됩니다. 세트 U에 시작점을 제외한 다른 점을 기록하고 인접 노드는 경로 값을 기록할 수 있으며 인접하지 않은 노드는 ∞로 기록됩니다. 그러면 다음 그림이 다음과 같이 표현됩니다.

        S={ A(0) },U={ B(4), C(2), D(3), E(∞), F(∞), G(∞), H(∞), I(∞ ) }

 첫 번째 단계:

  • S={A(0) }
  • U={ B(4), C(2) , D(3), E(∞), F(∞), G(∞), H(∞), I(∞) }

 2단계: C 경로는 이전 단계에서 가장 짧은 2입니다.

  • S={A(0), C(2) }
  • U={ B(4), D(3) , E(2+3=5), F(2+2=4), G(∞), H(∞), I(∞) }

 세 번째 단계: D 경로는 이전 단계에서 가장 짧은 3입니다.

  • S={A(0), C(2), D(3) }
  • U={ B(4) , E(5), F(4) , G(∞), H(∞), I(3+5=8) }

 4단계: 이전 단계에서 경로 B와 F가 가장 짧은 경로인 4입니다.

  • S={A(0), C(2), D(3),  B(4) }
  • U={ E(5), F(4) , G(4+5=9), H(∞), I(8) }

 5단계: 이전 단계의 F 경로가 가장 짧은 4

  • S={A(0), C(2), D(3), B(4), F(4) }
  • U={ E(5) , G(9), H(4+2=6), I(8) }

 6단계: 이전 단계의 E 경로가 가장 짧은 5

  • S={ A(0), C(2), D(3), B(4), F(4), E(5) }  
  • U={G(5+3=8), H(6) , I(8) }

 7단계: 이전 단계의 H 경로가 가장 짧은 6

  • S={ A(0), C(2), D(3), B(4), F(4), E(5), H(6 )  }
  • U={ 지(6+1=7) , 나는(8) }

 8단계: 이전 단계의 G 경로가 가장 짧은 7

  • S={ A(0), C(2), D(3), B(4), F(4), E(5), H(6), G(7 )  }
  • 유={ 나(8) }

 9단계: 이전 단계의 I 경로가 가장 짧은 8

  • S={ A(0), C(2), D(3), B(4), F(4), E(5), H(6), G(7), I(8  ) }
  • 유={ }

지금까지 A에서 각 지점까지의 최단 경로를 구했습니다.

둘째, JS 코드 구현

인스턴스 2를 예로 들어 보겠습니다.

  • 먼저 각 지점까지의 거리를 기록하는 그래프 배열을 정의합니다. 예를 들면 다음과 같습니다.
  1. A→A 거리는 0, A→B 거리는 4, A→C 거리는 2, A→D 거리는 3, A→E는 인접하지 않으므로 거리가 0...
  2. B→A는 비가역이므로 거리가 0, B→B 거리가 0, B→C 거리가 1, B→D가 인접하지 않으므로 거리가 0...

        등등

let graph = [
    [0,4,2,3,0,0,0,0,0],
    [0,0,1,0,0,0,5,0,0],
    [0,0,0,0,3,2,0,0,0],
    [0,0,1,0,0,1,0,0,5],
    [0,0,0,0,0,0,3,2,0],
    [0,0,0,0,1,0,0,2,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,0]
]
  • 현재 알려진 최단 경로를 기록하는 currentMinPth 배열을 정의하고 초기값은 무한대, 방문 배열을 정의하고 방문 여부를 기록하며 다음 방문 주기는 방문하지 않음
    let currentMinPth = [];
    let visited = [];
    for(let i = 0; i < graph.length;i++){
        currentMinPth.push(INF);
        visited.push(false);
    }
  • 시작점은 A, A→A는 0이므로 currentMinPth[0]은 0
  • 현재 알려진 노드 중에서 가장 가까운 노드를 찾아 인덱스 값 minIndex를 반환합니다(매번 최단 경로부터 시작).
function getMinIndex(currentMinPth,visited){
    let min = INF;
    let minIndex = -1;
    for(let i = 0; i < currentMinPth.length;i++){
        if(!visited[i]&&currentMinPth[i]<min){
            min = currentMinPth[i];
            minIndex = i;
        }
    }
    return minIndex
}
  • 방문한 것으로 얻은 가장 가까운 노드를 설정하십시오.
visited[minIndex] = true;
  • 인접 노드, 즉 graph[minIndex][i] !== 0인 노드를 찾아 인접 노드에 대한 경로 값을 currentMinPth로 업데이트하되, 이 값이 현재 값보다 작은 경우에만 해당됩니다.
if(!visited[i]&&
   graph[minIndex][i] !== 0 && 
   currentMinPth[minIndex] + graph[minIndex][i] < currentMinPth[i]){
   currentMinPth[i] = currentMinPth[minIndex] + graph[minIndex][i];
}
  • currentMinPth의 각 항목에 대해 위의 프로세스를 반복합니다. 길이 - 1이면 충분합니다. 마지막 하나만 남았을 때 확인할 필요가 없습니다. 전체 코드는 다음과 같습니다.
let graph = [
    [0,4,2,3,0,0,0,0,0],
    [0,0,1,0,0,0,5,0,0],
    [0,0,0,0,3,2,0,0,0],
    [0,0,1,0,0,1,0,0,5],
    [0,0,0,0,0,0,3,2,0],
    [0,0,0,0,1,0,0,2,0],
    [0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,0]
]
let INF = Number.MAX_SAFE_INTEGER;
function handlePath(){
    let currentMinPth = [];
    let visited = [];
    for(let i = 0; i < graph.length;i++){
        currentMinPth.push(INF);
        visited.push(false);
    }
    currentMinPth[0] = 0
    for(let j = 0; j < currentMinPth.length - 1;j++){
        let minIndex = getMinIndex(currentMinPth,visited);
        visited[minIndex] = true;
        for(let i = 0; i < currentMinPth.length;i++){
            if(!visited[i]&&
               graph[minIndex][i] !== 0 && 
               currentMinPth[minIndex] + graph[minIndex][i] < currentMinPth[i]){
               currentMinPth[i] = currentMinPth[minIndex] + graph[minIndex][i];
            }
        }
    }
    
    return currentMinPth
}
function getMinIndex(currentMinPth,visited){
    let min = INF;
    let minIndex = -1;
    for(let i = 0; i < currentMinPth.length;i++){
        if(!visited[i]&&currentMinPth[i]<min){
            min = currentMinPth[i];
            minIndex = i;
        }
    }
    return minIndex
}
console.log(handlePath())

요약하다

        이 글은 Dijkstra의 최단 경로 원리에 대한 간단한 이해와 js의 코드 구현을 기록한 것입니다.

추천

출처blog.csdn.net/sxww_zyt/article/details/129835779