-
자바스크립트로 구현하는 너비우선탐색(BFS) 깊이우선탐색(DFS)Programming/자료구조, 알고리즘 2020. 4. 8. 20:12반응형
패스트캠퍼스 코딩테스트 인터넷 강의, 잔재미코딩 님의 수업을 참고하였습니다.
BFS와 DFS란?
- 대표적인 그래프 탐색 알고리즘
- 너비 우선 탐색(Breadth First Search): 정점들과 같은 레벨에 있는 노드들(형제 노드들)을 먼저 탐색하는 방식
- 두 개의 큐를 사용한다.
- root와 가까운 node들부터 찾기 때문에 최단거리를 탐색할 때 유용하다.
- queue에 각 노드의 정보를 기록해야 하기 때문에 메모리를 많이 잡아 먹는다.
- 찾고자 하는 target node가 root node와 가까이 있다고 예상될 경우 BFS를 사용한다.
- 지도 어플에서 특정 위치까지의 최단거리 안내, 혹은 소셜미디어에서 친구 추천 등에 이용된다.
- 깊이 우선 탐색(Depth First Search): 정점의 자식들을 먼저 탐색하는 방식
- 한 개의 큐와 한 개의 스택을 사용한다.
- BFS보다 속도가 느릴 수 있다.
- 미로 게임 등에서 경로가 존재하는지를 판별할 때 유용하다.
- 너비 우선 탐색(Breadth First Search): 정점들과 같은 레벨에 있는 노드들(형제 노드들)을 먼저 탐색하는 방식
BFS/DFS 방식 이해를 위한 예제

- BFS 방식: A - B - C - D - G - H - I - E - F - J
- DFS 방식: A - B - D - E - F - C - G - H - I - J
자바스크립트로 그래프 표현하기
const graph = { A: ['B', 'C'], B: ['A', 'D'], C: ['A', 'G', 'H', 'I'], D: ['B', 'E', 'F'], E: ['D'], F: ['D'], G: ['C'], H: ['C'], I: ['C', 'J'], J: ['I'] };BFS 알고리즘 구현
구현
두 개의 큐(Queue)를 활용한다.
const graph = { A: ["B", "C"], B: ["A", "D"], C: ["A", "G", "H", "I"], D: ["B", "E", "F"], E: ["D"], F: ["D"], G: ["C"], H: ["C"], I: ["C", "J"], J: ["I"] }; const bfs = (graph, startNode) => { let visited = []; // 탐색을 마친 노드들 let needVisit = []; // 탐색해야할 노드들 needVisit.push(startNode); // 노드 탐색 시작 while (needVisit.length !== 0) { // 탐색해야할 노드가 남아있다면 const node = needVisit.shift(); // queue이기 때문에 선입선출, shift()를 사용한다. if (!visited.includes(node)) { // 해당 노드가 탐색된 적 없다면 visited.push(node); needVisit = [...needVisit, ...graph[node]]; } } return visited; }; console.log(bfs(graph, "A")); // ["A", "B", "C", "D", "G", "H", "I", "E", "F", "J"]DFS 알고리즘 구현
- 자료구조 스택과 큐를 활용
- needVisit 스택과 visited 큐, 두 개의 자료 구조를 생성한다.
- 큐와 스택 구현은 별도의 라이브러리를 활용할 수도 있지만 간단히 배열을 통해 구현하자.
BFS 구조는 두 개의 큐를 활용하는데, DFS는 한 개의 스택과 한 개의 큐를 사용한다는 차이가 있음
BFS 구조는 이전 노드와 연결된 노드들을 먼저 탐색해야 하기 때문에 queue. DFS는 이전 노드가 아니라 자기 자신과 연결되었던 노드들 먼저 탐색하기 때문에 stack을 사용한다.const graph = { A: ["B", "C"], B: ["A", "D"], C: ["A", "G", "H", "I"], D: ["B", "E", "F"], E: ["D"], F: ["D"], G: ["C"], H: ["C"], I: ["C", "J"], J: ["I"], }; // (graph, 시작 정점) const dfs = (graph, startNode) => { let needVisitStack = []; // 탐색을 해야 할 노드들 let visitedQueue = []; // 탐색을 마친 노드들 needVisitStack.push(startNode); // 탐색을 해야 할 노드가 남아 있다면 while (needVisitStack.length !== 0) { const node = needVisitStack.pop(); if (!visitedQueue.includes(node)) { visitedQueue.push(node); needVisitStack = [...needVisitStack, ...graph[node]]; } } return visitedQueue; }; console.log(dfs(graph, "A")); // ["A", "C", "I", "J", "H", "G", "B", "D", "F", "E"]시간복잡도
DFS와 BFS는 모두 노드 수+간선 수만큼의 복잡도를 지닌다. 즉, O(n)
반응형'Programming > 자료구조, 알고리즘' 카테고리의 다른 글
이진 탐색 (0) 2020.04.05 순차 탐색 (0) 2020.04.05 그리디 알고리즘 (2) 2020.04.03 분할정복과 병합정렬(merge sort), 퀵 정렬(quick sort) (0) 2020.04.01 동적계획법과 피보나치 수열 (0) 2020.03.31 - 대표적인 그래프 탐색 알고리즘