JavaScript

[JS] ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ๋Œ€๋น„ DFS(๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰) & BFS(๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰)

Irene1988 2025. 3. 2. 19:07

๐Ÿš€ DFS(๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰) & BFS(๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰) ๊ฐœ๋… ์ •๋ฆฌ

DFS์™€ BFS๋Š” ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ, ๊ทธ๋ž˜ํ”„๋‚˜ ํŠธ๋ฆฌ ๊ตฌ์กฐ์—์„œ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ฑฐ๋‚˜ ์ „์ฒด ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•  ๋•Œ ์‚ฌ์šฉ.

๐Ÿ”น 1. DFS(Depth-First Search, ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰)

DFS๋Š” ์ตœ๋Œ€ํ•œ ๊นŠ์ด ๋‚ด๋ ค๊ฐ€๋ฉด์„œ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ์‹.

 

๐Ÿ“Œ ํŠน์ง•:

  • ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ๊ณ„์† ํƒ์ƒ‰ํ•˜๋‹ค๊ฐ€ ๋” ์ด์ƒ ๊ฐˆ ๊ณณ์ด ์—†์œผ๋ฉด ๋˜๋Œ์•„์™€์„œ ๋‹ค๋ฅธ ๊ฒฝ๋กœ ํƒ์ƒ‰
  • ์Šคํƒ(Stack) ๋˜๋Š” ์žฌ๊ท€(Recursion)๋ฅผ ์‚ฌ์šฉ
  • ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•  ๋•Œ ์œ ์šฉ
  • ๋ฐฑํŠธ๋ž˜ํ‚น(Backtracking) ๋ฌธ์ œ์—์„œ ๋งŽ์ด ํ™œ์šฉ

๐Ÿ“Œ DFS ๋™์ž‘ ๋ฐฉ์‹:

  1. ํ˜„์žฌ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•˜๊ณ  ๋ฐฉ๋ฌธ ํ‘œ์‹œ
  2. ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ(์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ) ์ค‘ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ๋…ธ๋“œ๋กœ ์ด๋™
  3. ๋” ์ด์ƒ ๊ฐˆ ๊ณณ์ด ์—†์œผ๋ฉด ๋’ค๋กœ ๋Œ์•„๊ฐ(๋ฐฑํŠธ๋ž˜ํ‚น)
  4. ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต

๐ŸŽฏ 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 ๋ฐฉ์‹์œผ๋กœ ํƒ์ƒ‰)
  }
}

๐Ÿ” ์ฝ”๋“œ ๋™์ž‘ ๋ฐฉ์‹

  1. visited.has(node) → ์ด๋ฏธ ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ๋ฉด ๋ฆฌํ„ด
  2. ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ ์ถœ๋ ฅ ํ›„ visited์— ์ถ”๊ฐ€
  3. ํ˜„์žฌ ๋…ธ๋“œ์™€ ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ๋ฅผ 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 ๋™์ž‘ ๋ฐฉ์‹:

  1. ์‹œ์ž‘ ๋…ธ๋“œ๋ฅผ ํ์— ์ถ”๊ฐ€ํ•˜๊ณ  ๋ฐฉ๋ฌธ ํ‘œ์‹œ
  2. ํ์—์„œ ๋…ธ๋“œ๋ฅผ ๊บผ๋‚ด๊ณ  ํ•ด๋‹น ๋…ธ๋“œ์˜ ๋ชจ๋“  ์ธ์ ‘ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ
  3. ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ๋Š” ํ์— ์ถ”๊ฐ€
  4. ํ๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต

๐ŸŽฏ 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๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์–ด!

 

๐Ÿ† ์ •๋ฆฌ

  1. DFS(๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰)
    • ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ๊ณ„์† ํƒ์ƒ‰ ํ›„ ๋ฐฑํŠธ๋ž˜ํ‚น
    • ์Šคํƒ ๋˜๋Š” ์žฌ๊ท€ ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„
    • ๋ฐฑํŠธ๋ž˜ํ‚น ๋ฌธ์ œ์—์„œ ๋งŽ์ด ์‚ฌ์šฉ
    • ์˜ˆ: ๋ฏธ๋กœ ํƒ์ƒ‰, ํผ์ฆ ํ•ด๊ฒฐ
  2. BFS(๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰)
    • ๊ฐ€๊นŒ์šด ๋…ธ๋“œ๋ถ€ํ„ฐ ํƒ์ƒ‰
    • ํ(Queue) ๋ฅผ ์‚ฌ์šฉ
    • ์ตœ๋‹จ ๊ฒฝ๋กœ ๋ฌธ์ œ์—์„œ ํšจ๊ณผ์ 
    • ์˜ˆ: ๋ฏธ๋กœ์—์„œ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ์ฐพ๊ธฐ

 

 

 

 

*์œ„ ํฌ์ŠคํŒ…์€ ์ฑ—GPT ๋‹ต๋ณ€์„ ํ† ๋Œ€๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!