πŸ’» DEV/Algorithms & Data Structure

[Algorithm] κΉŠμ΄μš°μ„ νƒμƒ‰(DFS) κ³Ό λ„ˆλΉ„μš°μ„ νƒμƒ‰(BFS)

vodkassi 2021. 6. 30. 16:39
728x90

DFS 와 BFS λŠ” 각각 Depth-First Search 와 Breadth-First Search 둜, κΉŠμ΄μš°μ„ νƒμƒ‰κ³Ό λ„ˆλΉ„μš°μ„ νƒμƒ‰μ„ λœ»ν•œλ‹€. λ‘˜μ˜ 차이점과 μ½”λ“œ κ΅¬ν˜„ 방법을 ꡬ체적으둜 μ•Œμ•„λ³΄κ³ μž ν•œλ‹€.

 

BFS & DFS

BFS

  • κ·Έλž˜ν”„ μžλ£Œκ΅¬μ‘°ν˜•μ—μ„œ κ°€μž₯ κ°€κΉŒμš΄ λ…Έλ“œλΆ€ν„° μš°μ„ μ μœΌλ‘œ νƒμƒ‰ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€. 
  • 큐λ₯Ό μ΄μš©ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆλ‹€.

κ΅¬ν˜„ 단계

  1. 큐에 탐색 μ‹œμž‘ λ…Έλ“œλ₯Ό μ‚½μž…ν•œλ‹€.
  2. 큐의 front λ₯Ό λ°©λ¬Έν•  λ•Œλ§ˆλ‹€ λ°©λ¬Έ ν‘œμ‹œλ₯Ό ν•˜κ³ , popleft() λ₯Ό ν•œλ‹€.
  3. ν˜„μž¬ λ°©λ¬Έν•˜κ³  μžˆλŠ” λ…Έλ“œμ— λ°©λ¬Έν•˜μ§€ μ•Šμ€ 인접 λ…Έλ“œκ°€ μžˆλ‹€λ©΄ κ·Έ λ…Έλ“œλ₯Ό 큐에 λ„£λŠ”λ‹€
  4. ν˜„μž¬ λ°©λ¬Έν•˜κ³  μžˆλŠ” λ…Έλ“œμ— λ°©λ¬Έν•˜μ§€ μ•Šμ€ 인접 λ…Έλ“œκ°€ μ—†λ‹€λ©΄ 큐의 front 을 κΊΌλ‚Έλ‹€
  5. 반볡 μ‹€ν–‰ν•˜μ—¬ 큐가 μ™„μ „νžˆ 빌 λ•Œ μ’…λ£Œν•œλ‹€
from collections import deque # Python μ—μ„œ popleft() λ₯Ό ν•˜κΈ° μœ„ν•œ λͺ¨λ“ˆ

# λ…Έλ“œμ˜ λ²ˆν˜Έμ— 따라 μ—°κ²°λœ 정보λ₯Ό 2차원 λ°°μ—΄ ν‘œν˜„ν•  수 μžˆλ‹€. 
# κ°€λ Ή, 1 - 3 - 2 - 4 ν˜•νƒœλ‘œ μ—°κ²°λœ κ·Έλž˜ν”„λΌλ©΄, [[], [3], [3, 4], [1, 2], [2]] 둜 ν‘œν˜„ κ°€λŠ₯ν•˜λ‹€.
graph = [[], [3], [3, 4], [1, 2], [2]]

# λ°©λ¬Έ 처리λ₯Ό μœ„ν•œ 1차원 λ°°μ—΄
# μ΄ˆκΈ°κ°’μ„ False 둜 μ„€μ •ν•΄μ£Όμ–΄μ•Ό node λ₯Ό λ°©λ¬Έν•˜λ©΄ True 둜 μ „ν™˜ν•˜μ—¬ ν‘œμ‹œν•  수 μžˆλ‹€.
visited = [False] * (len(graph))

# λ°©λ¬Έν•΄μ•Όν•  λͺ©λ‘μ„ 담은 queue을 λ§Œλ“€μ–΄ while λ¬Έ μ‹€ν–‰
queue = deque([1]) # 첫 번째둜 λ°©λ¬Έν•  λ…Έλ“œ
while len(queue) > 0 :
	cur = queue.popleft()
    print(cur)
    for item in graph[cur]:
    	if visited[item] == False:
        	queue.append(item)
            visited[cur] = True

    	

DFS

  • κ·Έλž˜ν”„ μžλ£Œκ΅¬μ‘°ν˜•μ—μ„œ κ°€μž₯ κΉŠμ€ 뢀뢄을 (즉, 트리 κ΅¬μ‘°μ—μ„œ κ°€μž₯ ν•˜μœ„μ— μžˆλŠ” λ…Έλ“œλ₯Ό) λ¨Όμ € λ°©λ¬Έν•˜μ—¬ νƒμƒ‰ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€. 
  • μŠ€νƒ λ˜λŠ” μž¬κ·€λ₯Ό μ΄μš©ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆλ‹€.

κ΅¬ν˜„ 단계

  1. μŠ€νƒμ— 탐색 μ‹œμž‘ λ…Έλ“œλ₯Ό μ‚½μž…ν•œλ‹€
  2. μŠ€νƒμ˜ top 을 λ°©λ¬Έν•  λ•Œλ§ˆλ‹€ pop 으둜 μ‚­μ œν•˜κ³ , λ°©λ¬Έ ν‘œμ‹œλ₯Ό ν•œλ‹€
  3. ν˜„μž¬ λ°©λ¬Έν•˜κ³  μžˆλŠ” λ…Έλ“œμ— λ°©λ¬Έν•˜μ§€ μ•Šμ€ 인접 λ…Έλ“œκ°€ μžˆλ‹€λ©΄ κ·Έ λ…Έλ“œλ₯Ό μŠ€νƒμ— λ„£λŠ”λ‹€
  4. ν˜„μž¬ λ°©λ¬Έν•˜κ³  μžˆλŠ” λ…Έλ“œμ— λ°©λ¬Έν•˜μ§€ μ•Šμ€ 인접 λ…Έλ“œκ°€ μ—†λ‹€λ©΄ μŠ€νƒμ˜ top 을 κΊΌλ‚Έλ‹€
  5. 반볡 μ‹€ν–‰ν•˜μ—¬ μŠ€νƒμ΄ μ™„μ „νžˆ 빌 λ•Œ μ’…λ£Œν•œλ‹€
# λ…Έλ“œμ˜ λ²ˆν˜Έμ— 따라 μ—°κ²°λœ 정보λ₯Ό 2차원 λ°°μ—΄ ν‘œν˜„ν•  수 μžˆλ‹€. 
# κ°€λ Ή, 1 - 3 - 2 - 4 ν˜•νƒœλ‘œ μ—°κ²°λœ κ·Έλž˜ν”„λΌλ©΄, [[], [3], [3, 4], [1, 2], [2]] 둜 ν‘œν˜„ κ°€λŠ₯ν•˜λ‹€.
graph = [[], [3], [3, 4], [1, 2], [2]]

# λ°©λ¬Έ 처리λ₯Ό μœ„ν•œ 1차원 λ°°μ—΄
# μ΄ˆκΈ°κ°’μ„ False 둜 μ„€μ •ν•΄μ£Όμ–΄μ•Ό node λ₯Ό λ°©λ¬Έν•˜λ©΄ True 둜 μ „ν™˜ν•˜μ—¬ ν‘œμ‹œν•  수 μžˆλ‹€.
visited = [False] * (len(graph))

# 방법 1
# λ°©λ¬Έν•΄μ•Όν•  λͺ©λ‘μ„ 담은 stack을 λ§Œλ“€μ–΄ while λ¬Έ μ‹€ν–‰
stack = [1] # 첫 번째둜 λ°©λ¬Έν•  λ…Έλ“œ
while len(stack) > 0 :
	cur = stack.pop()
    print(cur)
    visited[cur] = True
    for item in graph[cur]:
    	if visited[item] == False:
        	stack.append(item)

방법 2
# μž¬κ·€μ μœΌλ‘œ μ‹€ν–‰ν•˜μ—¬ λ°©λ¬Έ μˆœμ„œλ₯Ό 좜λ ₯ν•˜λŠ” ν•¨μˆ˜
dfs(graph, node, visited):
	visited[node] = True
    print(node)
    for item in graph[node]:
    	if not visited[node]:
        	dfs(graph, item, visited)
    for i in graph[node]: