1. 문제 제기
너비 우선 탐색(Breadth-First Search, BFS)은 그래프나 트리 구조에서 유용하게 사용되는 탐색 알고리즘 중 하나입니다. 본 강좌에서는 BFS를 활용하여 “최단 경로 찾기” 문제를 해결해보겠습니다.
문제: 최단 경로 찾기
주어진 그래프에서 두 노드 사이의 최단 경로를 찾는 함수를 작성하시오. 그래프는 인접 리스트 형태로 주어지며, 노드는 문자열로 표현됩니다.
입력 형식
graph: { "A": ["B", "C"], "B": ["A", "D", "E"], "C": ["A", "F"], "D": ["B"], "E": ["B", "F"], "F": ["C", "E"] } start: "A" end: "F"
출력 형식
["A", "C", "F"]
2. 문제 분석
최단 경로를 찾기 위해 BFS를 사용하는 이유는 BFS가 한 번에 모든 이웃 노드를 탐색하기 때문에, 가장 빠른 경로를 보장하기 때문입니다. DFS(깊이 우선 탐색)와 달리 BFS는 현재 노드에 연결된 모든 노드를 먼저 탐색한 후, 다음 레벨로 이동합니다. 이 특징으로 인해 BFS는 최단 경로 탐색에 적합합니다.
3. 알고리즘 설계
다음은 BFS를 이용한 최단 경로 찾기 알고리즘의 기본 흐름입니다:
- 시작 노드를 큐에 추가하고 방문 표시를 합니다.
- 큐에서 노드를 하나 꺼내고, 그 노드의 이웃 노드를 모두 확인합니다.
- 이웃 노드 중 방문하지 않은 노드를 큐에 추가하고, 해당 노드의 부모 노드를 현재 노드로 설정합니다.
- 종료 노드를 찾기 전까지 2-3 단계를 반복합니다.
- 종료 노드에 도달했을 때, 부모 노드를 거꾸로 탐색하여 최단 경로를 작성합니다.
4. 코드 구현
아래는 BFS를 이용한 최단 경로 찾기 함수의 구현 코드입니다:
function findShortestPath(graph, start, end) { // 큐와 방문 표시를 위한 객체 let queue = [start]; let visited = {}; let parent = {}; visited[start] = true; parent[start] = null; while (queue.length > 0) { let currentNode = queue.shift(); // 큐에서 노드 제거 // 종료 노드에 도달한 경우 if (currentNode === end) { return reconstructPath(parent, start, end); } // 현재 노드의 이웃들 탐색 for (let neighbor of graph[currentNode]) { if (!visited[neighbor]) { visited[neighbor] = true; parent[neighbor] = currentNode; // 이웃 노드의 부모를 현재 노드로 설정 queue.push(neighbor); // 큐에 이웃 노드 추가 } } } return []; // 경로가 없을 경우 빈 배열 리턴 } function reconstructPath(parent, start, end) { let path = []; let current = end; while (current !== null) { path.push(current); current = parent[current]; } return path.reverse(); // 역순으로 경로 리턴 }
5. 알고리즘 분석
위 코드는 최단 경로를 찾기 위해 BFS를 사용하고 있습니다. 시간 복잡도는 O(V + E)로, V는 노드의 수, E는 간선의 수를 의미합니다. 이 알고리즘은 인접 리스트를 활용하기 때문에 메모리 효율적인 장점이 있습니다.
6. 시간 복잡도와 공간 복잡도 분석
시간 복잡도는 O(V + E)로, 모든 노드와 간선을 한 번씩 탐색하기 때문에 이와 같은 복잡도가 발생합니다. 공간 복잡도 또한 O(V)로 큐와 방문 표시 배열, 부모 저장 배열 등이 노드 수에 비례하기 때문입니다.
7. 테스트 케이스
위 코드를 확인하기 위해 몇 가지 테스트 케이스를 만들어 보겠습니다.
const graph = { "A": ["B", "C"], "B": ["A", "D", "E"], "C": ["A", "F"], "D": ["B"], "E": ["B", "F"], "F": ["C", "E"] }; console.log(findShortestPath(graph, "A", "F")); // Output: ["A", "C", "F"] console.log(findShortestPath(graph, "B", "F")); // Output: ["B", "E", "F"] console.log(findShortestPath(graph, "D", "A")); // Output: ["D", "B", "A"] console.log(findShortestPath(graph, "A", "A")); // Output: ["A"]
8. 마무리
이번 강좌에서는 자바스크립트로 너비 우선 탐색(BFS)을 이용하여 최단 경로를 찾는 문제를 해결해 보았습니다. BFS는 인접 리스트와 같은 구조를 활용해 그래프를 탐색하는 유용한 방법이며, 다양한 문제에 응용될 수 있습니다. 앞으로도 알고리즘을 연습하며 더 많은 문제를 해결해 나가길 바랍니다.
9. 추가 자료
더 많은 알고리즘 문제와 해법을 학습하고 싶다면 온라인 코딩 테스트 플랫폼을 이용해 보세요. 각종 문제와 힌트 등을 통해 실력을 더욱 향상시킬 수 있습니다.