[Algorithm] DFS&BFS

Updated:

๐Ÿ“ฃ
๋ณธ ํฌ์ŠคํŠธ๋Š” โ€˜์ด๊ฒƒ์ด ์ทจ์—…์„ ์œ„ํ•œ ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ๋‹ค with ํŒŒ์ด์ฌโ€™์„ ๊ณต๋ถ€ํ•˜๊ณ  ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค :)
click > (์ด์ฝ”ํ…Œ 2021) ์ด๊ฒƒ์ด ์ทจ์—…์„ ์œ„ํ•œ ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ๋‹ค with ํŒŒ์ด์ฌ

DFS/BFS

์ด๋ก 

  • ํƒ์ƒ‰(Search)

    ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ ์ค‘์—์„œ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๋Š” ๊ณผ์ • โ†’ ๊ทธ๋ž˜ํ”„, ํŠธ๋ฆฌ ๋“ฑ์˜ ์ž๋ฃŒ๊ตฌ์กฐ์—์„œ ๋งŽ์ด ๋‹ค๋ฃฌ๋‹ค.

์ž๋ฃŒ๊ตฌ์กฐ(Data Structure)

๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์กฐ

  • Stack : ์„ ์ž… ํ›„์ถœ (First In Last Out) or ํ›„์ž… ์„ ์ถœ (Last In First Out)
    • [์˜ˆ์ œ 5-1] ์Šคํƒ ์˜ˆ์ œ

        # stack example
              
        stack = []
              
        # ์‚ฝ์ž…(5)-์‚ฝ์ž…(2)-์‚ฝ์ž…(3)-์‚ฝ์ž…(7)-์‚ญ์ œ()-์‚ฝ์ž…(1)-์‚ฝ์ž…(4)-์‚ญ์ œ()
        stack.append(5)
        stack.append(2)
        stack.append(3)
        stack.append(7)
        stack.pop()
        stack.append(1)
        stack.append(4)
        stack.pop()
              
        print(stack) # ์ตœํ•˜๋‹จ ์›์†Œ๋ถ€ํ„ฐ
        print(stack[::-1]) # ์ตœ์ƒ๋‹จ ์›์†Œ๋ถ€ํ„ฐ
      
  • Queue : ์„ ์ž… ์„ ์ถœ (First In First Out)
    • [์˜ˆ์ œ 5-2] ํ ์˜ˆ์ œ

        from collections import deque
              
        # ํ ๊ตฌํ˜„์„ ์œ„ํ•ด deque ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉ
        queue = deque()
              
        # ์‚ฝ์ž…(5)-์‚ฝ์ž…(2)-์‚ฝ์ž…(3)-์‚ฝ์ž…(7)-์‚ญ์ œ()-์‚ฝ์ž…(1)-์‚ฝ์ž…(4)-์‚ญ์ œ()
        queue.append(5)
        queue.append(2)
        queue.append(3)
        queue.append(7)
        queue.popleft()
        queue.append(1)
        queue.append(4)
        queue.popleft()
              
        print(queue) # ๋จผ์ € ๋“ค์–ด์˜จ ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ
        queue.reverse() # ์—ญ์ˆœ์œผ๋กœ ์žฌ์ •๋ ฌ
        print(queue) # ๋‚˜์ค‘์— ๋“ค์–ด์˜จ ์›์†Œ๋ถ€ํ„ฐ ์ถœ๋ ฅ
      
  • Recursive Function : ์ž๊ธฐ ์ž์‹ ์„ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜
    • [์˜ˆ์ œ 5-3] ์žฌ๊ท€ํ•จ์ˆ˜ ์˜ˆ์ œ

        def factorial_iterative(n):
            result = 1
            for i in range(1,n+1):
                result *= i
            return result
              
        def factorial_recursive(n):
            if n <= 1:
                return 1
            return n * factorial_recursive(n-1)
              
        print(factorial_iterative(5))
        print(factorial_recursive(5))
      
  • Graph์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ

    image

    • ๋…ธ๋“œ (Node) : ์ •์ (Vertex)๋ผ๊ณ ๋„ ํ•œ๋‹ค.
    • ๊ฐ„์„  (Edge) : ๋‘ ๋…ธ๋“œ๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.
  • Graph์˜ ํ‘œํ˜„ ๋ฐฉ์‹
    • ์ธ์ ‘ ํ–‰๋ ฌ (Adjacency Matrix) : 2์ฐจ์› ๋ฐฐ์—ด๋กœ ํ‘œํ˜„
      • ๋ชจ๋“  ๊ด€๊ณ„๋ฅผ ์ €์žฅํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋งŽ์ด ์‚ฌ์šฉ
      • [์˜ˆ์ œ 5-4] ์ธ์ ‘ ํ–‰๋ ฌ ์˜ˆ์ œ

          INF = 999999999
                    
          # 2์ฐจ์› ๋ฆฌ์ŠคํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ธ์ ‘ํ–‰๋ ฌ ํ‘œํ˜„
          graph = [
              [0, 7, 5],
              [7, 0, INF],
              [5, INF, 0]
          ]
                    
          print(graph)
        
    • ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ (Adjacency List) : ๋ฆฌ์ŠคํŠธ๋กœ ํ‘œํ˜„
      • ํŠน์ • ๋‘ ๋…ธ๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด ์–ป๋Š” ์†๋„ ๋А๋ฆผ
      • [์˜ˆ์ œ 5-5] ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ ์˜ˆ์ œ

          # ํ–‰์ด 3๊ฐœ์ธ 2์ฐจ์› ๋ฆฌ์ŠคํŠธ๋กœ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ ํ‘œํ˜„
          graph = [[] for _ in range(3)]
                    
          # ๋…ธ๋“œ 0์— ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ ์ •๋ณด ์ €์žฅ(๋…ธ๋“œ, ๊ฑฐ๋ฆฌ)
          graph[0].append((1,7))
          graph[0].append((2,5))
                    
          # ๋…ธ๋“œ 1์— ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ ์ •๋ณด ์ €์žฅ(๋…ธ๋“œ, ๊ฑฐ๋ฆฌ)
          graph[1].append((0,7))
                    
          # ๋…ธ๋“œ 2์— ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ ์ •๋ณด ์ €์žฅ(๋…ธ๋“œ, ๊ฑฐ๋ฆฌ)
          graph[2].append((0,5))
                    
          print(graph)
        

๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰์œผ๋กœ ๊ทธ๋ž˜ํ”„์—์„œ ๊นŠ์€ ๋ถ€๋ถ„์„ ๋จผ์ € ํƒ์ƒ‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ Stack ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•œ๋‹ค.

  1. ํƒ์ƒ‰ ์‹œ์ž‘ ๋…ธ๋“œ๋ฅผ ์Šคํƒ์— ์‚ฝ์ž…ํ•˜๊ณ  ๋ฐฉ๋ฌธ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.
  2. ์Šคํƒ์˜ ์ตœ์ƒ๋‹จ ๋…ธ๋“œ์— ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ์ธ์ ‘ ๋…ธ๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ ์ธ์ ‘ ๋…ธ๋“œ๋ฅผ ์Šคํƒ์— ๋„ฃ๊ณ  ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค. ๋ฐ˜๋ฌธํ•˜์ง€ ์•Š์€ ์ธ์ ‘ ๋…ธ๋“œ๊ฐ€ ์—†์œผ๋ฉด ์Šคํƒ์—์„œ ์ตœ์ƒ๋‹จ ๋…ธ๋“œ๋ฅผ ๊บผ๋‚ธ๋‹ค.
  3. 2์˜ ๊ณผ์ •์„ ๋” ์ด์ƒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•œ๋‹ค.

๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ N๊ฐœ์ธ ๊ฒฝ์šฐ O(N)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค.

  • [์˜ˆ์ œ 5-6] DFS ์˜ˆ์ œ

      # DFS ๋ฉ”์„œ๋“œ ์ •์˜
      def dfs(graph, v, visited):
          # ํ˜„์žฌ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ
          visited[v] = True
          print(v, end=' ')
          # ํ˜„์žฌ ๋…ธ๋“œ์™€ ์—ฐ๊ฒฐ๋œ ๋‹ค๋ฅธ ๋…ธ๋“œ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ๋ฐฉ๋ฌธ
          for i in graph[v]:
              if not visited[i]:
                  dfs(graph, i, visited)
        
      # ๊ฐ ๋…ธ๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์ •๋ณด๋ฅผ ๋ฆฌ์ŠคํŠธ ์ž๋ฃŒํ˜•์œผ๋กœ ํ‘œํ˜„(2์ฐจ์› ๋ฆฌ์ŠคํŠธ)
      graph = [
          [],
          [2,3,8],
          [1,7],
          [1,4,5],
          [3,5],
          [3,4],
          [7],
          [2,6,8],
          [1,7]
      ]
        
      # ๊ฐ ๋…ธ๋“œ๊ฐ€ ๋ฐฉ๋ฌธ๋œ ์ •๋ณด๋ฅผ ๋ฆฌ์ŠคํŠธ ์ž๋ฃŒ
      # ํ˜•์œผ๋กœ ํ‘œํ˜„(1์ฐจ์› ๋ฆฌ์ŠคํŠธ)
      visited = [False] * 9
        
      # ์ •์˜๋œ DFS ํ•จ์ˆ˜ ํ˜ธ์ถœ
      dfs(graph, 1, visited)
    

๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰์œผ๋กœ ๊ฐ€๊นŒ์šด ๋…ธ๋“œ๋ถ€ํ„ฐ ํƒ์ƒ‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ Queue ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•œ๋‹ค.

  1. ํƒ์ƒ‰ ์‹œ์ž‘ ๋…ธ๋“œ๋ฅผ ํ์— ์‚ฝ์ž…ํ•˜๊ณ  ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.
  2. ํ์—์„œ ๋…ธ๋“œ๋ฅผ ๊บผ๋‚ด ํ•ด๋‹น ๋…ธ๋“œ์˜ ์ธ์ ‘ ๋…ธ๋“œ ์ค‘์—์„œ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ๋…ธ๋“œ๋ฅผ ๋ชจ๋‘ ํ์— ์‚ฝ์ž…ํ•˜๊ณ  ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.
  3. 2์˜ ๊ณผ์ •์„ ๋” ์ด์ƒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•œ๋‹ค.

๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ N๊ฐœ์ธ ๊ฒฝ์šฐ O(N)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์‹ค์ œ ์ˆ˜ํ–‰ ์‹œ๊ฐ„์€ DFS๋ณด๋‹ค ์ข‹์€ ํŽธ์ด๋‹ค.

  • [์˜ˆ์ œ 5-7] BFS ์˜ˆ์ œ

      from collections import deque
        
      # BFS ๋ฉ”์„œ๋“œ ์ •์˜
      def bfs(graph, start, visited):
          # ํ ๊ตฌํ˜„์„ ์œ„ํ•ด deque ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ
          queue = deque([start])
          # ํ˜„์žฌ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ์ฒ˜๋ฆฌ
          visited[start] = True
          # ํ๊ฐ€ ๋นŒ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
          while queue:
              # ํ์—์„œ ํ•˜๋‚˜์˜ ์›์†Œ๋ฅผ ๋ฝ‘์•„ ์ถœ๋ ฅ
              v = queue.popleft()
              print(v, end=" ")
              # ํ•ด๋‹น ์›์†Œ์™€ ์—ฐ๊ฒฐ๋œ, ์•„์ง ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ์›์†Œ๋“ค์„ ํ์— ์‚ฝ์ž…
              for i in graph[v]:
                  if not visited[i]:
                      queue.append(i)
                      visited[i] = True
        
      # ๊ฐ ๋…ธ๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์ •๋ณด๋ฅผ ๋ฆฌ์ŠคํŠธ ์ž๋ฃŒํ˜•์œผ๋กœ ํ‘œํ˜„(2์ฐจ์› ๋ฆฌ์ŠคํŠธ)
      graph = [
          [],
          [2,3,8],
          [1,7],
          [1,4,5],
          [3,5],
          [3,4],
          [7],
          [2,6,8],
          [1,7]
      ]
        
      # ๊ฐ ๋…ธ๋“œ๊ฐ€ ๋ฐฉ๋ฌธ๋œ ์ •๋ณด๋ฅผ ๋ฆฌ์ŠคํŠธ ์ž๋ฃŒ
      # ํ˜•์œผ๋กœ ํ‘œํ˜„(1์ฐจ์› ๋ฆฌ์ŠคํŠธ)
      visited = [False] * 9
        
      # ์ •์˜๋œ DFS ํ•จ์ˆ˜ ํ˜ธ์ถœ
      bfs(graph, 1, visited)
    

์‹ค์ „๋ฌธ์ œ

[์‹ค์ „๋ฌธ์ œ 1] ์Œ๋ฃŒ์ˆ˜ ์–ผ๋ ค ๋จน๊ธฐ

N, M = map(int, input().split())

graph = []
for i in range(N):
    graph.append(list(map(int, input())))

# DFS๋กœ ํŠน์ •ํ•œ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•œ ๋’ค์— ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  ๋…ธ๋“œ๋“ค๋„ ๋ฐฉ๋ฌธ
def dfs(x,y):
    if x <= -1 or x >= N or y <= -1 or y >= N:
        return False
    if graph[x][y] == 0:
        graph[x][y] = 1
        dfs(x - 1, y)
        dfs(x, y - 1)
        dfs(x + 1, y)
        dfs(x, y + 1)
    return False

result = 0
for i in range(N):
    for j in range(M):
        if dfs(i,j) == True:
            result += 1

print(result)

[์‹ค์ „ ๋ฌธ์ œ 2] ๋ฏธ๋กœ ํƒˆ์ถœ

from collections import deque

# N, M์„ ๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ž…๋ ฅ๋ฐ›๊ธฐ
n, m = map(int, input().split())
# 2์ฐจ์› ๋ฆฌ์ŠคํŠธ์˜ ๋งต ์ •๋ณด ์ž…๋ ฅ๋ฐ›๊ธฐ
graph = []
for i in range(n):
    graph.append(list(map(int, input())))

# ์ด๋™ํ•  ๋„ค ๋ฐฉํ–ฅ ์ •์˜
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

# BFS ๊ตฌํ˜„
def bfs(x, y):
    # ํ ๊ตฌํ˜„์„ ์œ„ํ•ด deque ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ
    queue = deque()
    queue.append((x,y))
    # ํ๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
    while queue:
        x, y = queue.popleft()
        # ํ˜„์žฌ ์œ„์น˜์—์„œ ๋„ค ๋ฐฉํ–ฅ์œผ๋กœ ์œ„์น˜ ํ™•์ธ
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if nx < 0 or ny < 0 or nx >= n or ny >= m:
                continue
            if graph[nx][ny] == 0:
                continue
            # ํ•ด๋‹น ๋…ธ๋“œ๋ฅผ ์ฒ˜์Œ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ฒฝ์šฐ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๊ธฐ๋ก
            if graph[nx][ny] == 1:
                graph[nx][ny] = graph[x][y] + 1
                queue.append((nx,ny))
    # ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ ์•„๋ž˜(n,m)๊นŒ์ง€ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ ๋ฐ˜ํ™˜
    return graph[n-1][m-1]

print(bfs(0,0))

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ