[Algorithm] 다익스트라 알고리즘

2025. 2. 8. 00:08· → 알고리즘 관련
목차
  1. 🕸️ 다익스트라 알고리즘
  2. 🔥 Swift 구현
  3. 🧭 초기 세팅
  4. 🚏 가장 가까운 노드 찾기
  5. ♻️ 최단거리 갱신
  6. 💾 입력과 결과
  7. 🔨 우선순위 큐를 사용한 다익스트라의 개선

🕸️ 다익스트라 알고리즘

그래프의 한 정점에서 모든 정점까지의 최단거리를 구하는 알고리즘이다.

출처: 위키피디아

각 정점을 방문하면서 그 정점에 도달하는 최소값을 갱신해주는 방식이다. 다음 정점을 선택할 때 시작정점으로부터 가장 짧은 거리의 정점을 방문해야 한다.

🔥 Swift 구현

실제 구현은 아래와 같다. 아래의 방법으로 구할 경우 다익스트라의 시간 복잡도는 O(V^2 + E)이다.

struct Edge {
    var d: Int
    var w: Int
}

func dijkstra(graph: [[Edge]], start: Int) -> [Int] {
    var distances = Array(repeating: Int.max, count: graph.count)
    var visited = Array(repeating: false, count: graph.count)
    distances[start] = 0 // 시작 정점의 거리 0
    
    for _ in 0..<graph.count {
        var minDistance = Int.max
        var current = -1
        
        /// 가장 짧은 거리의 다음 정점 찾기
        for vertex in 0..<graph.count {
            if !visited[vertex] && distances[vertex] < minDistance {
                minDistance = distances[vertex]
                current = vertex
            }
        }
        
        if current == -1 { break }
        visited[current] = true
        
        /// 간선 정보를 통해 최단거리 갱신
        for edge in graph[current] {
            distances[edge.d] = min(distances[current] + edge.w, distances[edge.d])
        }
    }
    
    return distances
}

🧭 초기 세팅

아래와 같이 리턴할 거리의 배열을 Int.max로 초기화 해준다. 방문체크를 하기 위한 방문배열도 선언해주고... 시작 정점은 거리 0으로 설정한다.

func dijkstra(graph: [[Edge]], start: Int) -> [Int] {
    var distances = Array(repeating: Int.max, count: graph.count)
    var visited = Array(repeating: false, count: graph.count)
    distances[start] = 0 // 시작 정점의 거리 0
    
    //... 생략
}

🚏 가장 가까운 노드 찾기

물론 이부분을 우선순위 큐로 구현한다면 달라지지만 O(N)으로 단순하게 구한다고 생각하면 아래와 같이 방문하지 않은 정점중에서 가장 가까운 거리의 정점을 찾아준다. 

        var minDistance = Int.max
        var current = -1
        
        /// 가장 짧은 거리의 다음 노드 찾기
        for vertex in 0..<graph.count {
            if !visited[vertex] && distances[vertex] < minDistance {
                minDistance = distances[vertex]
                current = vertex
            }
        }
        
        if current == -1 { break }

♻️ 최단거리 갱신

간선 정보를 통해 최단거리를 갱신해준다. 여기서 d는 destination, w는 weight의 약자를 썼다.

        visited[current] = true
        
        /// 간선 정보를 통해 최단거리 갱신
        for edge in graph[current] {
            distances[edge.d] = min(distances[current] + edge.w, distances[edge.d])
        }

💾 입력과 결과

아래와 같이 간선(Edge)가 입력된다면 다익스트라를 활용하면 O(V^2 + E)로 각 정점까지 최단거리를 구할 수 있다!

출처: 위키피디아

let graph: [[Edge]] = [
    [Edge(d: 1, w: 7), Edge(d: 2, w: 9), Edge(d: 5, w: 14)],                    // Vertex 0
    [Edge(d: 0, w: 7), Edge(d: 2, w: 10), Edge(d: 3, w: 15)],                   // Vertex 1
    [Edge(d: 0, w: 9), Edge(d: 1, w: 10), Edge(d: 3, w: 11), Edge(d: 5, w: 2)], // Vertex 2
    [Edge(d: 1, w: 15), Edge(d: 2, w: 11), Edge(d: 4, w: 6)],                   // Vertex 3
    [Edge(d: 3, w: 6), Edge(d: 5, w: 9)],                                       // Vertex 4
    [Edge(d: 0, w: 14), Edge(d: 2, w: 2), Edge(d: 4, w: 9)]                     // Vertex 5
]

print(dijkstra(graph: graph, start: 0)) // [0, 7, 9, 20, 20, 11]

🔨 우선순위 큐를 사용한 다익스트라의 개선

위에서 구현한 것은 처음 고안된 알고리즘이다. 가장 최단거리의 노드를 찾기위해서 모든 정점을 계속 돌면서 체크하게 되는데 이부분을 우선순위 큐(최소 힙)으로 구현하게 된다면, 아래와 같이 구현할 수 있다. 이렇게 되면 시간복잡도는 O(VlogV + ElogV)로 줄어들게 된다.

func dijkstra(_ graph: [[Edge]], _ start: Int) -> [Int] {
    var distances = [Int](repeating: Int.max, count: graph.count)
    distances[start] = 0
    
    var priorityQueue = MinHeap()
    priorityQueue.push((vertex: start, cost: 0))
    
    while !priorityQueue.isEmpty {
        guard let current = priorityQueue.pop() else { break }

        if current.cost > distances[current.vertex] { continue }

        for edge in graph[current.vertex] {
            let cost = current.cost + edge.w
            if cost < distances[edge.d] {
                distances[edge.d] = cost
                priorityQueue.push((vertex: edge.d, cost: cost))
            }
        }
    }
    
    return distances
}

'→ 알고리즘 관련' 카테고리의 다른 글

[Algorithm] 벨먼 포드 알고리즘  (0) 2025.02.08
[Algorithm] 플로이드 워셜 알고리즘  (1) 2025.02.08
[Algorithm] 0-1 배낭문제(Knapsack Problem) - 백트래킹  (0) 2025.02.07
[Algorithm] 0-1 배낭문제(Knapsack Problem) - DP  (0) 2025.02.07
[Algorithm] 2차원 배열 회전하기 (Swift)  (0) 2025.01.30
  1. 🕸️ 다익스트라 알고리즘
  2. 🔥 Swift 구현
  3. 🧭 초기 세팅
  4. 🚏 가장 가까운 노드 찾기
  5. ♻️ 최단거리 갱신
  6. 💾 입력과 결과
  7. 🔨 우선순위 큐를 사용한 다익스트라의 개선
'→ 알고리즘 관련' 카테고리의 다른 글
  • [Algorithm] 벨먼 포드 알고리즘
  • [Algorithm] 플로이드 워셜 알고리즘
  • [Algorithm] 0-1 배낭문제(Knapsack Problem) - 백트래킹
  • [Algorithm] 0-1 배낭문제(Knapsack Problem) - DP
Swift librarian
Swift librarian
Swift librarian
Swift Library
Swift librarian
전체
오늘
어제
  • 분류 전체보기 (231)
    • 📺 Programming (5)
    • → Architecture (2)
    • → Design Pattern (0)
    • → Computer Science (15)
    • ⚙️ Algorithm (0)
    • → 알고리즘 관련 (22)
    • → Problems (104)
    • 🚀 Project (0)
    • → 알쏭달쏭 (0)
    • → Shook (2)
    • → Solver (8)
    • → Taster (7)
    • → Outline (4)
    • → Pointer (2)
    • → Guesser (3)
    • 🦜 Swift (2)
    • → Swift Archive (12)
    • → Swift Study (12)
    • → Xcode (6)
    • 🧰 Framework (0)
    • → Foundation (1)
    • → UIKit (2)
    • → SwiftUI (3)
    • → CoreData (2)
    • → MapKit (1)
    • → CoreHaptic (1)
    • → User Notification (1)
    • → StoreKit (2)
    • 🏛️ Library (0)
    • → TCA (0)
    • 🐈‍⬛ Git (8)
    • → Git의 원리 (2)
    • → Git 심화 (1)
    • 📦 Other (1)
    • 👦🏻 Log (0)

최근 글

hELLO · Designed By 정상우.v4.2.2
Swift librarian
[Algorithm] 다익스트라 알고리즘
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.