BFS, DFS 두가지 모두 그래프를 탐색(Graph Traverse)하는 방법입니다.
그래프란, 정점(node)과 그 정점을 연결하는 간선(edge)으로 이루어진 자료구조의 일종을 말하며, 그래프를 탐색한다는 것은 하나의 정점으로부터 시작하여 차례대로 모든 정점들을 한 번씩 방문하는 것을 말한다.
BFS
graph = {
'A' : ['B','C'],
'B' : ['A', 'D'],
'C' : ['A', 'E'],
'D' : ['B', 'E', 'F'],
'E' : ['C', 'D', 'F'],
'F' : ['D', 'E']
};
bfs(start_vertex = "A") {
const queue = [start_vertex];
const result = [];
const visited = {};
let currentVertex;
visited[start_vertex] = true;
while(queue.length) {
currentVertex = queue.shift();
result.push(currentVertex);
graph[currentVertex].forEach(neighbor => {
if(!visited[neighbor]) {
visited[neighbor] = true;
queue.push(neighbor);
}
});
}
return result;
}
DFS
graph = {
'A' : ['B','C'],
'B' : ['A', 'D'],
'C' : ['A', 'E'],
'D' : ['B', 'E', 'F'],
'E' : ['C', 'D', 'F'],
'F' : ['D', 'E']
};
dfs(start_vertex = "A") {
const stack = [start_vertex];
const result = [];
const visited = {};
let currentVertex;
visited[start] = true;
while(stack.length) {
currentVertex = stack.pop();
result.push(currentVertex);
graph[currentVertex].forEach(neighbor => {
if(!visited[neighbor]) {
visited[neighbor] = true;
stack.push(neighbor);
}
});
}
return result;
}
recursive_dfs(start_vertex = "A") {
const result = [];
const visited = {};
(function dfs(vertex) {
if(!vertex) return null;
visited[vertex] = true;
result.push(vertex);
graph[vertex].forEach(neighbor => {
if(!visited[neighbor]) {
return dfs(neighbor);
}
});
})(start_vertex);
return result;
}
언제 DFS, BFS를 이용하나요?
문제 유형별로 어떤 알고리즘이 더 유리한지 서술한다.
- 🚫 : impossible
- 👍 : good and possible
- 👎 : bad but possible
index | Problem | BFS | DFS |
---|---|---|---|
1 | 그래프의 모든 정점을 방문 하는 문제 | 👍 | 👍 |
2 | 각 경로마다 특징을 저장해둬야 하는 문제 | 👎 | 👍 |
3 | 최단거리 문제 | 👍 | 👎 |
4 | 문제의 그래프가 매우 클 경우 | 🚫 | 👍 |
5 | 검색 시작 지점과 원하는 대상이 가까이 있을 경우 | 👍 | 👎 |