๐ DFS(๊น์ด ์ฐ์ ํ์) & BFS(๋๋น ์ฐ์ ํ์) ๊ฐ๋ ์ ๋ฆฌ
DFS์ BFS๋ ๊ทธ๋ํ ํ์ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก, ๊ทธ๋ํ๋ ํธ๋ฆฌ ๊ตฌ์กฐ์์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ฑฐ๋ ์ ์ฒด ๋
ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ๋ ์ฌ์ฉ.
๐น 1. DFS(Depth-First Search, ๊น์ด ์ฐ์ ํ์)
DFS๋ ์ต๋ํ ๊น์ด ๋ด๋ ค๊ฐ๋ฉด์ ํ์ํ๋ ๋ฐฉ์.
๐ ํน์ง:
- ํ ๋ฐฉํฅ์ผ๋ก ๊ณ์ ํ์ํ๋ค๊ฐ ๋ ์ด์ ๊ฐ ๊ณณ์ด ์์ผ๋ฉด ๋๋์์์ ๋ค๋ฅธ ๊ฒฝ๋ก ํ์
- ์คํ(Stack) ๋๋ ์ฌ๊ท(Recursion)๋ฅผ ์ฌ์ฉ
- ๊ทธ๋ํ์ ๋ชจ๋ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ๋ ์ ์ฉ
- ๋ฐฑํธ๋ํน(Backtracking) ๋ฌธ์ ์์ ๋ง์ด ํ์ฉ
๐ DFS ๋์ ๋ฐฉ์:
- ํ์ฌ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ๊ณ ๋ฐฉ๋ฌธ ํ์
- ๋ฐฉ๋ฌธํ ๋ ธ๋์ ์์ ๋ ธ๋(์ฐ๊ฒฐ๋ ๋ ธ๋) ์ค ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋๋ก ์ด๋
- ๋ ์ด์ ๊ฐ ๊ณณ์ด ์์ผ๋ฉด ๋ค๋ก ๋์๊ฐ(๋ฐฑํธ๋ํน)
- ๋ชจ๋ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ๋๊น์ง ๋ฐ๋ณต
๐ฏ DFS ์์ (์ฌ๊ท ๋ฐฉ์)
const graph = {
1: [2, 3, 4],
2: [5, 6],
3: [],
4: [7],
5: [],
6: [],
7: []
};
const visited = new Set();
function dfs(node) {
if (visited.has(node)) return; // ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋
ธ๋๋ฉด ๋ฆฌํด
console.log(node); // ํ์ฌ ๋
ธ๋ ์ถ๋ ฅ
visited.add(node); // ๋ฐฉ๋ฌธ ํ์
for (const neighbor of graph[node]) { // ์ฐ๊ฒฐ๋ ๋
ธ๋ ํ์
dfs(neighbor);
}
}
dfs(1);
๐น ์คํ ๊ฒฐ๊ณผ:
1
2
5
6
3
4
7
๐ 1 → 2 → 5 → 6 → 3 → 4 → 7 ์์๋ก ํ์๋จ.
์์ธํ ์ฝ๋ํ์ด
1๏ธโฃ ๊ทธ๋ํ ์ ์
const graph = {
1: [2, 3, 4], // 1๋ฒ ๋
ธ๋๋ 2, 3, 4๋ฒ ๋
ธ๋์ ์ฐ๊ฒฐ๋จ
2: [5, 6], // 2๋ฒ ๋
ธ๋๋ 5, 6๋ฒ ๋
ธ๋์ ์ฐ๊ฒฐ๋จ
3: [], // 3๋ฒ ๋
ธ๋๋ ์ฐ๊ฒฐ๋ ๋
ธ๋๊ฐ ์์
4: [7], // 4๋ฒ ๋
ธ๋๋ 7๋ฒ ๋
ธ๋์ ์ฐ๊ฒฐ๋จ
5: [], // 5, 6, 7๋ฒ ๋
ธ๋๋ ๋ ์ด์ ์ฐ๊ฒฐ๋ ๋
ธ๋๊ฐ ์์
6: [],
7: []
};
- ๊ทธ๋ํ๋ ๊ฐ์ฒด๋ก ํํํ๊ณ , ๊ฐ ํค(๋ ธ๋ ๋ฒํธ)์ ์ฐ๊ฒฐ๋ ๋ ธ๋๋ค์ ๋ฐฐ์ด์ ์ ์ฅํ์ด.
- ์๋ฅผ ๋ค์ด, 1: [2, 3, 4]๋ ๋ ธ๋ 1์ด 2, 3, 4์ ์ฐ๊ฒฐ๋์ด ์๋ค๋ ๋ป์ด์ผ.
2๏ธโฃ ๋ฐฉ๋ฌธํ ๋ ธ๋๋ฅผ ์ ์ฅํ๋ Set (์ค๋ณต ๋ฐฉ์ง)
const visited = new Set();
- Set์ ์ค๋ณต์ ํ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์, ๋ฐฉ๋ฌธํ ๋ ธ๋๋ฅผ ์ ์ฅํด์ ์ค๋ณต ํ์์ ๋ฐฉ์งํ ์ ์์ด.
- ๋ฐฉ๋ฌธํ ๋ ธ๋๋ฅผ ๊ธฐ์ตํ์ง ์์ผ๋ฉด ๋ฌดํ ๋ฃจํ์ ๋น ์ง ์๋ ์์ด!
3๏ธโฃ DFS ํจ์ ๊ตฌํ
const graph = {
1: [2, 3, 4],
2: [5, 6],
3: [],
4: [7],
5: [],
6: [],
7: []
};
const visited = new Set();
function dfs(node) {
if (visited.has(node)) return; // ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋
ธ๋๋ฉด ๋ฆฌํด
console.log(node); // ํ์ฌ ๋
ธ๋ ์ถ๋ ฅ
visited.add(node); // ๋ฐฉ๋ฌธ ํ์
graph[node].forEach(neighbor => {
dfs(neighbor); // ์ฌ๊ท ํธ์ถ
});
}
dfs(1);
function dfs(node) {
if (visited.has(node)) return; // ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋
ธ๋๋ฉด ๋ฆฌํด
console.log(node); // ํ์ฌ ๋ฐฉ๋ฌธํ ๋
ธ๋ ์ถ๋ ฅ
visited.add(node); // ๋ฐฉ๋ฌธํ ๋
ธ๋๋ฅผ Set์ ์ถ๊ฐ
for (const neighbor of graph[node]) { // ํ์ฌ ๋
ธ๋์ ์ฐ๊ฒฐ๋ ๋ชจ๋ ๋
ธ๋ ํ์
dfs(neighbor); // ์ฌ๊ท ํธ์ถ (DFS ๋ฐฉ์์ผ๋ก ํ์)
}
}
๐ ์ฝ๋ ๋์ ๋ฐฉ์
- visited.has(node) → ์ด๋ฏธ ๋ฐฉ๋ฌธํ ๋ ธ๋๋ฉด ๋ฆฌํด
- ๋ฐฉ๋ฌธํ ๋ ธ๋ ์ถ๋ ฅ ํ visited์ ์ถ๊ฐ
- ํ์ฌ ๋ ธ๋์ ์ฐ๊ฒฐ๋ ๋ ธ๋๋ฅผ for ๋ฌธ์ผ๋ก ํ๋์ฉ ๊บผ๋ด์ dfs(neighbor) ์ฌ๊ท ํธ์ถ
4๏ธโฃ DFS ์คํ
dfs(1);
๐ ์คํ ๊ณผ์ (์คํ ๊ตฌ์กฐ๋ก ํ์ ์งํ)
1 → 2 → 5 → 6 → (๋ฐฑํธ๋ํน) → 3 → (๋ฐฑํธ๋ํน) → 4 → 7
๐ก ์คํ ๊ฒฐ๊ณผ
1
2
5
6
3
4
7
๐ DFS๋ ๊น์ด ์ฐ์ ์ด๋ฏ๋ก, ํ ๋ฐฉํฅ์ผ๋ก ๋๊น์ง ํ์ ํ ๋ฐฑํธ๋ํน!
๐น 2. BFS(Breadth-First Search, ๋๋น ์ฐ์ ํ์)
BFS๋ ๊ฐ๊น์ด ๋ ธ๋๋ถํฐ ํ์ํ๋ ๋ฐฉ์
๐ ํน์ง:
- ๋ชจ๋ ์ธ์ ํ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ํ, ๋ค์ ๊น์ด์ ๋ ธ๋๋ฅผ ํ์
- ํ(Queue)๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ
- ์ต๋จ ๊ฒฝ๋ก ๋ฌธ์ ์์ ๋ง์ด ์ฌ์ฉ
๐ BFS ๋์ ๋ฐฉ์:
- ์์ ๋ ธ๋๋ฅผ ํ์ ์ถ๊ฐํ๊ณ ๋ฐฉ๋ฌธ ํ์
- ํ์์ ๋ ธ๋๋ฅผ ๊บผ๋ด๊ณ ํด๋น ๋ ธ๋์ ๋ชจ๋ ์ธ์ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธ
- ๋ฐฉ๋ฌธํ ๋ ธ๋๋ ํ์ ์ถ๊ฐ
- ํ๊ฐ ๋น ๋๊น์ง ๋ฐ๋ณต
๐ฏ BFS ์์ (ํ ๋ฐฉ์)
function bfs(start) {
const queue = [start];
const visited = new Set();
visited.add(start);
while (queue.length > 0) {
const node = queue.shift(); // ํ์์ ๋
ธ๋ ๊บผ๋ด๊ธฐ
console.log(node);
for (const neighbor of graph[node]) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
}
}
}
}
bfs(1);
๐น ์คํ ๊ฒฐ๊ณผ:
1
2
3
4
5
6
7
๐ 1 → 2 → 3 → 4 → 5 → 6 → 7 ์์๋ก ํ์๋จ.
๐ฅ DFS vs BFS ์ฐจ์ด์ ์ ๋ฆฌ
DFS (๊น์ด ์ฐ์ ํ์) | BFS (๋๋น ์ฐ์ ํ์) | |
ํ์ ๋ฐฉ์ | ํ ๊ฒฝ๋ก๋ฅผ ๋๊น์ง ํ์ ํ ๋ฐฑํธ๋ํน | ํ์ฌ ๋ ธ๋์ ์ธ์ ๋ ธ๋๋ถํฐ ํ์ |
์๋ฃ๊ตฌ์กฐ | ์คํ(Stack) ๋๋ ์ฌ๊ท(Recursion) | ํ(Queue) |
์ฌ์ฉ ์์ | ๋ฐฑํธ๋ํน (๋ฏธ๋ก ํ์, ํผ์ฆ) | ์ต๋จ ๊ฒฝ๋ก ๋ฌธ์ (๊ธธ ์ฐพ๊ธฐ) |
๊ณต๊ฐ ๋ณต์ก๋ | O(V) (์ฌ๊ท ํธ์ถ๋ก ๊น์ด๋งํผ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ) | O(V) (ํ์ ๋ชจ๋ ๋ ธ๋ ์ ์ฅ) |
์๊ฐ ๋ณต์ก๋ | O(V + E) | O(V + E) |
๐ ์ ๋ฆฌํ์๋ฉด:
- DFS: ๊น์ด ๋จผ์ ํ์ → ๋ฐฑํธ๋ํน์ด ํ์ํ ๋ ์ ์ฉ
- BFS: ๊ฐ๊น์ด ๊ณณ๋ถํฐ ํ์ → ์ต๋จ ๊ฒฝ๋ก ์ฐพ๊ธฐ์ ์ ํฉ
๐ฏ DFS & BFS ํ์ฉ ์์
โ 1๏ธโฃ ๋ฏธ๋ก์์ ์ต๋จ ๊ฑฐ๋ฆฌ ์ฐพ๊ธฐ (BFS ํ์ฉ)
๋ฏธ๋ก์์ ์ต๋จ ๊ฑฐ๋ฆฌ ์ฐพ๊ธฐ๋ BFS๊ฐ ์ ํฉํด!
function shortestPath(maze, start, end) {
const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]; // ์ด๋ ๋ฐฉํฅ (์, ํ, ์ข, ์ฐ)
const queue = [[...start, 0]]; // [x, y, ๊ฑฐ๋ฆฌ]
const visited = new Set();
visited.add(start.toString());
while (queue.length > 0) {
const [x, y, dist] = queue.shift();
if (x === end[0] && y === end[1]) return dist; // ๋์ฐฉํ๋ฉด ๊ฑฐ๋ฆฌ ๋ฐํ
for (const [dx, dy] of directions) {
const nx = x + dx, ny = y + dy;
if (maze[nx]?.[ny] === 0 && !visited.has([nx, ny].toString())) {
queue.push([nx, ny, dist + 1]);
visited.add([nx, ny].toString());
}
}
}
return -1; // ๋์ฐฉ ๋ถ๊ฐ๋ฅํ ๊ฒฝ์ฐ
}
const maze = [
[0, 0, 1, 0],
[1, 0, 1, 0],
[0, 0, 0, 0],
[0, 1, 1, 0]
];
console.log(shortestPath(maze, [0, 0], [3, 3])); // ์ต๋จ ๊ฑฐ๋ฆฌ ์ถ๋ ฅ
๐ ๋ฏธ๋ก์์ BFS๋ฅผ ์ฌ์ฉํ๋ฉด ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ ์ ์์ด!
๐ ์ ๋ฆฌ
- DFS(๊น์ด ์ฐ์ ํ์)
- ํ ๋ฐฉํฅ์ผ๋ก ๊ณ์ ํ์ ํ ๋ฐฑํธ๋ํน
- ์คํ ๋๋ ์ฌ๊ท ํจ์๋ก ๊ตฌํ
- ๋ฐฑํธ๋ํน ๋ฌธ์ ์์ ๋ง์ด ์ฌ์ฉ
- ์: ๋ฏธ๋ก ํ์, ํผ์ฆ ํด๊ฒฐ
- BFS(๋๋น ์ฐ์ ํ์)
- ๊ฐ๊น์ด ๋ ธ๋๋ถํฐ ํ์
- ํ(Queue) ๋ฅผ ์ฌ์ฉ
- ์ต๋จ ๊ฒฝ๋ก ๋ฌธ์ ์์ ํจ๊ณผ์
- ์: ๋ฏธ๋ก์์ ์ต๋จ ๊ฑฐ๋ฆฌ ์ฐพ๊ธฐ
*์ ํฌ์คํ ์ ์ฑGPT ๋ต๋ณ์ ํ ๋๋ก ์์ฑ๋์์ต๋๋ค!
'JavaScript' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JS] ๊ฐ์ฒด์ ๋ฐฐ์ด์ ๊ตฌ์กฐ ๋ถํด ํ ๋น (Destructuring Assignment) (1) | 2025.03.04 |
---|---|
[JS] ์ฌ๊ท ๊ธฐ๋ฅ (0) | 2025.03.02 |
[JS] some()๊ณผ reduce()์ ๋ํด~ (0) | 2025.02.27 |
[JS] ์๋ฐ์คํฌ๋ฆฝํธ split() ๋ฉ์๋ (0) | 2025.02.19 |
[JS] ์๋ฐ์คํฌ๋ฆฝํธ์ ์กฐ๊ฑด๋ฌธ ์ ๋ฆฌ (0) | 2025.02.18 |