๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

์ฝ”ํ…Œ

[์ด์ฝ”ํ…Œ/Python] DFS / BFS

DFS์™€ BFS๋Š” ๋Œ€ํ‘œ์ ์ธ ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

 

์—ฌ๊ธฐ์„œ 'ํƒ์ƒ‰'์€ ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ ์ค‘์—์„œ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๋Š” ๊ณผ์ •์„ ๋œปํ•œ๋‹ค.

DFS์™€ BFS๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์Šคํƒ, ํ ์ž๋ฃŒ๊ตฌ์กฐ์™€ ์žฌ๊ท€ํ•จ์ˆ˜์— ๋Œ€ํ•ด ์ˆ™์ง€ํ•ด์•ผ ํ•œ๋‹ค.


 

์Šคํƒ

  • ์„ ์ž…ํ›„์ถœ (๋จผ์ € ๋“ค์–ด์˜ค๋ฉด ๋‚˜์ค‘์— ๋‚˜๊ฐ)
  • DFS ๊ตฌํ˜„์— ์‚ฌ์šฉ๋จ
stack = []

stack.append(5)
stack.append(2)
stack.append(3)
stack.append(7)
stack.pop()
stack.append(1)
stack.append(4)
stack.pop()

print(stack)       # ์ตœํ•˜๋‹จ ์›์†Œ๋ถ€ํ„ฐ ์ถœ๋ ฅ (๋“ค์–ด์˜จ ์ˆœ์œผ๋กœ) -> [5, 2, 3, 1]

print(stack[::-1]) # ์ตœ์ƒ๋‹จ ์›์†Œ๋ถ€ํ„ฐ ์ถœ๋ ฅ (์ตœ๊ทผ์— ๋“ค์–ด์˜จ) -> [1, 3, 2, 5]
# or
stack.reverse()
print(stack())     # [1, 3, 2, 5]

 

 

ํ

  • ์„ ์ž…์„ ์ถœ (๋จผ์ € ๋“ค์–ด์˜ค๋ฉด ๋จผ์ € ๋‚˜๊ฐ)
  • BFS ๊ตฌํ˜„์— ์‚ฌ์šฉ๋จ
from collections import deque

queue = deque()      # ๊ฒฐ๊ณผ: deque([])
queue2 = deque([1])  # ๊ฒฐ๊ณผ: deque([1])

queue.append(5)
queue.append(2)
queue.append(3)
queue.append(7)
queue.popleft()
queue.append(1)
queue.append(4)
queue.popleft()

print(queue())   # ๋“ค์–ด์˜จ ์ˆœ์œผ๋กœ ์ถœ๋ ฅ -> deque([3, 7, 1, 4])
queue.reverse()  # ์—ญ์ˆœ
print(queue())   # ๋‚˜์ค‘์— ๋“ค์–ด์˜จ ์ˆœ์œผ๋กœ -> deque([4, 1, 7, 3])

 

 

์žฌ๊ท€ํ•จ์ˆ˜

  • ์ข…๋ฃŒ ์กฐ๊ฑด์„ ๋ฐ˜๋“œ์‹œ ๋ช…์‹œํ•ด์•ผ ํ•จ: ๋ช…์‹œํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌดํ•œํžˆ ํ˜ธ์ถœ๋˜๋‹ค๊ฐ€ RecursionError ๋ฐœ์ƒ
  • ํ•จ์ˆ˜์˜ ์ •๋ณด๊ฐ€ ์Šคํƒ ํ”„๋ ˆ์ž„์— ๋‹ด๊ฒจ ์ฐจ๋ก€๋Œ€๋กœ ํ˜ธ์ถœ๋˜์—ˆ๋‹ค๊ฐ€ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜๋ถ€ํ„ฐ ์ข…๋ฃŒ๋จ → ์Šคํƒ ํ˜•ํƒœ๋กœ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— DFS ๊ตฌํ˜„์— ์‚ฌ์šฉ๋จ
  • ๋ชจ๋“  ์žฌ๊ท€ ํ•จ์ˆ˜๋Š” ๋ฐ˜๋ณต๋ฌธ์„ ์ด์šฉํ•ด ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ (๋ฐ˜๋Œ€๋„ ์„ฑ๋ฆฝ)
def recursive_function(i):
    if i == 100:
        return
    print(f'{i}๋ฒˆ์งธ ์žฌ๊ท€ ํ•จ์ˆ˜์—์„œ {i+1}๋ฒˆ์งธ ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.')
    recursive_function(i + 1)
    print(f'{i}๋ฒˆ์งธ ์žฌ๊ท€ ํ•จ์ˆ˜๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.')

recursive_function(1)

 


DFS

  • Depth-First Search, ๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰ → ๊นŠ์€ ๋ถ€๋ถ„์„ ์šฐ์„ ์ ์œผ๋กœ ํƒ์ƒ‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

๋™์ž‘ ๊ณผ์ •

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

⇒ ์ฆ‰, ๋งค๋ฒˆ ์ตœ์ƒ๋‹จ ์›์†Œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ, ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ์ธ์ ‘ ๋…ธ๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ ์ธ์ ‘ํ•œ ๋…ธ๋“œ๋กœ๋„ ๋ฐฉ๋ฌธ ์ˆ˜ํ–‰

 

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 = [
    [],         # ๋…ธ๋“œ ๋ฒˆํ˜ธ๊ฐ€ 1๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ๋น„์›Œ๋‘ 
    [2, 3, 8],  # 1๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
    [1, 7],     # 2๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ 
    [1, 4, 5],  # 3๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
    [3, 5],     # 4๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
    [3, 4],     # 5๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
    [7],        # 6๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
    [2, 6 ,8],  # 7๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
    [1, 7]      # 8๋ฒˆ ๋…ธ๋“œ์™€ ์ธ์ ‘ํ•œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
]
    
visited = [False] * 9   # graph์™€ ๊ฐ™์€ ํฌ๊ธฐ๋กœ (0~8), ๋ฐฉ๋ฌธ์€ 1๋ถ€ํ„ฐ
dfs(graph, 1, visited)  # 1 2 7 6 8 3 4 5

 

 

BFS

  • Breadth-First Search, ๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰ → ๊ฐ€๊นŒ์šด ๋…ธ๋“œ๋ถ€ํ„ฐ ์šฐ์„ ์ ์œผ๋กœ ํƒ์ƒ‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • ํŠน์ • ์กฐ๊ฑด์—์„œ์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ชฉ์ ์œผ๋กœ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉ๋จ

๋™์ž‘ ๊ณผ์ •

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

 

BFS ์˜ˆ์ œ

from collections import deque

def bfs(graph, start, visited):
    # Step 1) ์‹œ์ž‘ ๋…ธ๋“œ๋ฅผ ํ์— ์‚ฝ์ž…ํ•˜๊ณ  ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ
    queue = deque([start])
    visited[start] = True
    
    # Step 3) ํ๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
    while queue:
        # Step 2)
        # ๋จผ์ € ๋“ค์–ด์˜จ ์›์†Œ ํ•˜๋‚˜ ๋ฝ‘์•„ ์ถœ๋ ฅ
        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]
]
    
visited = [False] * 9
bfs(graph, 1, visited)  # 1 2 3 8 7 4 5 6

 

'์ฝ”ํ…Œ' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[์ด์ฝ”ํ…Œ/Python] ์Œ๋ฃŒ์ˆ˜ ์–ผ๋ ค ๋จน๊ธฐ (DFS)  (0) 2024.06.02
[SWEA/Python] 1928. Base64 Decoder  (0) 2024.05.19