μš”μ•½

  • DFSλŠ” μ‹œμž‘ λ…Έλ“œμ—μ„œ μžμ‹ λ…Έλ“œλ₯Ό 깊이 μš°μ„ μœΌλ‘œ νƒμƒ‰ν•˜λ©° 주둜 μŠ€νƒμ΄λ‚˜ μž¬κ·€ ν•¨μˆ˜λ₯Ό 톡해 κ΅¬ν˜„ν•˜λŠ” λ°©μ‹μž…λ‹ˆλ‹€.
  • 이 방식은 λ©”λͺ¨λ¦¬ 효율이 μ’‹κ³  κ·Έλž˜ν”„ μˆœν™˜ 감지에 μœ λ¦¬ν•˜μ§€λ§Œ μ΅œλ‹¨ 경둜 νƒμƒ‰μ—λŠ” μ ν•©ν•˜μ§€ μ•ŠμœΌλ©° λ¬΄ν•œ λ£¨ν”„μ˜ μœ„ν—˜μ΄ μžˆμŠ΅λ‹ˆλ‹€.
  • BFSλŠ” μΈμ ‘ν•œ λ…Έλ“œλ“€μ„ λ¨Όμ € νƒμƒ‰ν•˜λŠ” λ„ˆλΉ„ μš°μ„  λ°©μ‹μœΌλ‘œ μ„ μž…μ„ μΆœ ꡬ쑰인 큐λ₯Ό ν™œμš©ν•˜μ—¬ κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  • κ°€μ€‘μΉ˜κ°€ μ—†λŠ” κ·Έλž˜ν”„μ—μ„œ μ΅œλ‹¨ 경둜λ₯Ό μ°ΎλŠ” 데 νƒμ›”ν•˜μ§€λ§Œ λ…Έλ“œ μˆ˜κ°€ λ§Žκ±°λ‚˜ λΆ„κΈ° κ³„μˆ˜κ°€ 클수둝 λ©”λͺ¨λ¦¬ μ†Œλͺ¨κ°€ μ‹¬ν•©λ‹ˆλ‹€.
  • λ”°λΌμ„œ λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©λ¬Έν•˜κ±°λ‚˜ κΉŠμ€ 탐색이 ν•„μš”ν•˜λ©΄ DFSλ₯Ό, μ΅œλ‹¨ 거리λ₯Ό ꡬ해야 ν•œλ‹€λ©΄ BFSλ₯Ό μ„ νƒν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.

1. DFS (Depth-First Search, 깊이 μš°μ„  탐색)

1. 1 κ°œλ…

μ‹œμž‘ λ…Έλ“œμ—μ„œ μžμ‹ λ…Έλ“œλ“€μ„ 깊이λ₯Ό μš°μ„ μœΌλ‘œ μˆœμ„œλŒ€λ‘œ νƒμƒ‰ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜

깊이 μš°μ„ μœΌλ‘œ λͺ¨λ“  경우의 수λ₯Ό νƒμƒ‰ν•˜λŠ” μ™„μ „ 탐색 μ•Œκ³ λ¦¬μ¦˜μ— μ†ν•˜μ§€λ§Œ, 항상 κ·Έλ ‡μ§€λŠ” μ•Šλ‹€. Stack을 ν™œμš©ν•œ λ°˜λ³΅λ¬Έμ— μ“°μ΄κ±°λ‚˜, μž¬κ·€λ¬Έμ„ 톡해 κ΅¬ν˜„λœλ‹€.

1.2 탐색과정

DFS의 κΈ°λ³Έ 탐색과정은 νŠΉμ • λ…Έλ“œμ—μ„œ μ‹œμž‘ν•˜μ—¬ 역좔적(Backtracking) ν•˜κΈ° 전에 κ°€λŠ₯ν•œ μžμ‹ λ…Έλ“œλ“€μ„ 멀리 νƒμƒ‰ν•œλ‹€.

  1. νŠΉμ • λ…Έλ“œλ₯Ό λ°©λ¬Έν–ˆμœΌλ©΄, λ°©λ¬Έν–ˆλ‹€κ³  ν‘œμ‹œ
  2. ν•΄λ‹Ή λ…Έλ“œμ˜ μžμ‹ λ…Έλ“œλ₯Ό 탐색
  3. 더이상 μžμ‹ λ…Έλ“œκ°€ μ—†μœΌλ©΄ 역좔적
  4. λ°©λ¬Έν•œ 적이 μ—†λŠ” λ…Έλ“œλ₯Ό 탐색
  5. λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©λ¬Έν•  λ•Œ κΉŒμ§€ μœ„ ν”„λ‘œμ„ΈμŠ€ 반볡

1.3 νŠΉμ§•

μž₯점

  1. DFSλŠ” ν˜„μž¬ 순회 쀑인 λ…Έλ“œλ§Œ μ €μž₯ν•˜λŠ” μŠ€νƒ 데이터 ꡬ쑰λ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— BFS에 λΉ„ν•΄ λ©”λͺ¨λ¦¬ 곡간 덜 μ°¨μ§€ν•œλ‹€.
  2. νŠΉμ • λ…Έλ“œ λ˜λŠ” λͺ¨λ“  λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜λŠ” 것이 λͺ©μ μ΄λΌλ©΄ μœ μš©ν•˜λ‹€.
  3. κ·Έλž˜ν”„ μˆœν™˜ 감지가 κ°€λŠ₯ν•˜λ‹€.

단점

  1. κ·Έλž˜ν”„ ꡬ쑰가 μˆœν™˜μΈ 경우, λ¬΄ν•œ 루프에 빠질 수 μžˆλ‹€.
  2. 두 λ…Έλ“œ μ‚¬μ΄μ˜ μ΅œλ‹¨ 경둜λ₯Ό μ°ΎμœΌλ €λŠ” 경우 μ ν•©ν•˜μ§€ μ•Šμ€ μ•Œκ³ λ¦¬μ¦˜

1.4 κ΅¬ν˜„ 방법

# μ˜ˆμ‹œ κ·Έλž˜ν”„
graph = { 
	1 : [2,3,4], 
	2 : [5], 
	3 : [5], 
	4 : [], 
	5 : [6,7], 
	6 : [], 
	7 : [3]
}

반볡 κ΅¬ν˜„ (stack)

  • 데이터가 차곑차곑 μŒ“μ•„ μ˜¬λ¦¬λŠ” ν˜•νƒœλ‘œ, κ°€μž₯ λ§ˆμ§€λ§‰μ— μ‚½μž…λœ 데이터가 κ°€μž₯ λ¨Όμ € μ‚­μ œλ˜λŠ” ꡬ쑰
  • pushΒ : μƒˆλ‘œμš΄ 데이터λ₯Ό κ°€μž₯ 맨 μœ„(top)μœ„μΉ˜μ— μ‚½μž…
  • pop: 맨 μœ„(top) 데이터λ₯Ό 제거

μŠ€νƒ 데이터 ꡬ쑰λ₯Ό μ‚¬μš©ν•˜μ—¬ 반볡 κ΅¬ν˜„μ„ 톡해 λ°©λ¬Έν•  λ…Έλ“œλ₯Ό μΆ”μ ν•œλ‹€.

  1. μž„μ˜μ˜ λ…Έλ“œλ₯Ό μ‹œμž‘μ μœΌλ‘œ λ°©λ¬Έν•œ κ²ƒμœΌλ‘œ ν‘œμ‹œν•˜κ³  μŠ€νƒμ— push
  2. top에 μœ„μΉ˜ν•œ λ…Έλ“œλ₯Ό κ°€μ Έμ˜¨λ‹€.
  3. λ°©λ¬Έν•˜μ§€ μ•Šμ€ λͺ¨λ“  인접 λ…Έλ“œλ₯Ό λ°©λ¬Έν•œ ν›„ λ°©λ¬Έν•œ ν‘œμ‹œλ₯Ό μŠ€νƒμ— push
  4. μŠ€νƒμ΄ λΉ„μ›Œμ§ˆ λ•Œ κΉŒμ§€ 반볡
def stack_dfs(root):
    visited = []
    stack = [root]
    
    while stack:
        v = stack.pop()
        if v not in visited:
            visited.append(v)
            for w in graph[v]:
                stack.append(w)
    
    return visited
 
print(stack_dfs(1)) #[1,4,3,5,7,6,2]

μž¬κ·€ κ΅¬ν˜„

μž¬κ·€ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ κ·Έλž˜ν”„μ˜ λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©λ¬Έν•œλ‹€. ν˜„μž¬ λ…Έλ“œμ™€ λ°©λ¬Έν•œ 집합을 μž…λ ₯κ°’μœΌλ‘œ μ‚¬μš©ν•˜κ³  아직 λ°©λ¬Έν•˜μ§€ μ•Šμ€ λͺ¨λ“  μΈμ ‘ν•œ λ…Έλ“œμ— DFSλ₯Ό μ μš©ν•œλ‹€.

μœ„ 방법은 λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©λ¬Έν•˜λŠ” 것이 λͺ©μ μΌ λ•Œ μœ μš©ν•˜λ‹€.

def recursive_dfs(root, visited=[]): 
	visited.append(root) 
	
	for w in graph[root]: 
		if w not in visited: 
			visited = recursive_dfs(w, visited) 
	return visited
 
print(recursive_dfs(1, [])) #[1,2,]

비ꡐ

두 방법 λͺ¨λ‘ μ‹œκ°„ 및 곡간 λ³΅μž‘λ„λŠ” λ™μΌν•˜λ‹€.

일반적으둜 반볡 κ΅¬ν˜„(Stack)은 호좜 μŠ€νƒμ„ μ‚¬μš©ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 곡간 μΈ‘λ©΄μ—μ„œ 더 효율적 μž¬κ·€ κ΅¬ν˜„μ€ 반볡 κ΅¬ν˜„λ³΄λ‹€ κ°„λ‹¨ν•˜κ³  κ°„κ²°ν•˜μ—¬ 가독성이 μ’‹λ‹€. κ·ΈλŸ¬λ‚˜ κ·Έλž˜ν”„ 크기가 ν¬κ±°λ‚˜ μˆœν™˜ ꡬ쑰인 경우 μŠ€νƒ μ˜€λ²„ν”Œλ‘œ λ°œμƒν•œλ‹€.


2. BFS(Breadth-First Search, λ„ˆλΉ„ μš°μ„  탐색)

2.1 κ°œλ…

μ‹œμž‘ λ…Έλ“œμ—μ„œ μžμ‹ λ…Έλ“œλ“€μ„ λ„ˆλΉ„λ₯Ό μš°μ„ μœΌλ‘œ μˆœμ„œλŒ€λ‘œ νƒμƒ‰ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜

BFSλŠ” μ™„μ „ 탐색 μ•Œκ³ λ¦¬μ¦˜μ— μ†ν•˜λ©°, κ°€μ€‘μΉ˜κ°€ μ—†λŠ” κ·Έλž˜ν”„μ—μ„œ λ™μΌν•œ 거리에 μžˆλŠ” λͺ¨λ“  λ…Έλ“œλ₯Ό νƒμƒ‰ν•œλ‹€. 이후 거리의 λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜κΈ° μ‹œμž‘ν•˜λŠ” 방식이닀.

λ”°λΌμ„œ, κ°€μ€‘μΉ˜κ°€ μ—†λŠ” κ·Έλž˜ν”„μ—μ„œ μ΅œλ‹¨κ±°λ¦¬λ₯Ό κ΅¬ν•˜λŠ” λ¬Έμ œμ— ν™œμš©λœλ‹€. Queueλ₯Ό ν™œμš©ν•΄ λ‹€μŒ λ°©λ¬Έν•  λ…Έλ“œλ₯Ό μΆ”μ ν•˜κ±°λ‚˜, While λ°˜λ³΅λ¬Έμ„ ν†΅ν•œ 문제λ₯Ό ν•΄κ²°ν•œλ‹€.

2.2 탐색 κ³Όμ •

  • μ„ μž…μ„ μΆœ(FIFO, First In First Out)둜 λ¨Όμ € λ“€μ–΄μ˜¨ 데이터가 λ¨Όμ € λ‚˜κ°€λŠ” λ°©μ‹μ˜ μ„ ν˜• 자료ꡬ쑰
  • frontμ—μ„œ 데이터λ₯Ό μ‚­μ œ(dequeue)ν•œλ‹€.
  • rearμ—μ„œ 데이터λ₯Ό μ‚½μž…(enqueue)ν•œλ‹€.
  1. μ‹œμž‘ λ…Έλ“œμ—μ„œ μ‹œμž‘ν•˜κ³  λŒ€κΈ°μ—΄(Queue)에 μ‚½μž…ν•œλ‹€.
  2. λŒ€κΈ°μ—΄μ—μ„œ λ…Έλ“œλ₯Ό μ œκ±°ν•˜κ³  검사(poll = dequeue)ν•œλ‹€.
  3. κ²€μ‚¬ν•œ λ…Έλ“œκ°€ λͺ©ν‘œ λ…Έλ“œλΌλ©΄ 검색 μ™„λ£Œ
  4. κ·Έλ ‡μ§€ μ•Šμ€ 경우, κ²€μ‚¬ν•œ λ…Έλ“œμ— μ†ν•œ μžμ‹ λ…Έλ“œ 쀑 λ°©λ¬Έν•˜μ§€ μ•Šμ€ μžμ‹ λ…Έλ“œλ₯Ό 큐에 λ„£λŠ”λ‹€(offer = enqueue)
  5. λŒ€κΈ°μ—΄μ΄ λΉ„μ–΄ μžˆκ±°λ‚˜ λͺ©ν‘œ λ…Έλ“œλ₯Ό 찾을 λ•ŒκΉŒμ§€ μœ„ 단계 λ°˜λ³΅ν•œλ‹€.

2.3 νŠΉμ§•

μž₯점

  1. κ°„λ‹¨ν•˜κ³  μ΄ν•΄ν•˜κΈ° 쉽닀.
  2. μ—°κ²°λœ ꡬ성 μš”μ†Œμ—μ„œ λͺ¨λ“  λ…Έλ“œλ₯Ό μ°ΎλŠ”λ° μ‚¬μš© κ°€λŠ₯ν•˜λ‹€.

단점

  1. λ§Žμ€ λ©”λͺ¨λ¦¬κ°€ ν•„μš”ν•˜λ―€λ‘œ κ·Έλž˜ν”„κ°€ 큰 경우 μ ν•©ν•˜μ§€ μ•Šλ‹€.
  2. κ·Έλž˜ν”„ 순회 μ‹œ, κ°€μ€‘μΉ˜ κ³ λ €ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— κ°€μ€‘μΉ˜ 링크가 μžˆλŠ” κ·Έλž˜ν”„μ—λŠ” μ ν•©ν•˜μ§€ μ•Šλ‹€.
  3. λ‹€μŒ 깊이둜 μ΄λ™ν•˜κΈ° 전에 λ…Έλ“œμ˜ λͺ¨λ“  ν•˜μœ„ ν•­λͺ©μ„ νƒμƒ‰ν•˜κΈ° λ•Œλ¬Έμ— λΆ„κΈ° κ³„μˆ˜κ°€ 큰 κ·Έλž˜ν”„μ—λŠ” λΉ„νš¨μœ¨μ μ΄λ‹€.(λΆ„κΈ° κ³„μˆ˜λž€, 각 λ…Έλ“œκ°€ ν‰κ· μ μœΌλ‘œ κ°€μ§€κ³  μžˆλŠ” μžμ‹ λ…Έλ“œμ˜ 개수)
  4. λ‹€μŒ 깊이둜 μ΄λ™ν•˜κΈ° 전에 ν˜„μž¬ 깊이의 λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©λ¬Έν•˜κΈ° λ•Œλ¬Έμ— λ…Έλ“œ μˆ˜κ°€ λ§Žμ€ κ·Έλž˜ν”„μ—λŠ” λΉ„νš¨μœ¨μ μ΄λ‹€.
  5. λͺ©ν‘œ λ…Έλ“œκ°€ μ‹œμž‘ λ…Έλ“œμ—μ„œ 멀리 λ–¨μ–΄μ Έ 있으면 λ‹€μŒ 깊이둜 μ΄λ™ν•˜κΈ° 전에 μ£Όμ–΄μ§„ 깊이의 λͺ¨λ“  λ…Έλ“œλ₯Ό νƒμƒ‰ν•˜κΈ° λ•Œλ¬Έμ— λΉ„νš¨μœ¨μ μ΄λ‹€.

비ꡐ

  • BFSλŠ” λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ 많고, λ…Έλ“œ μˆ˜κ°€ λ§Žμ€ κ·Έλž˜ν”„μ—λŠ” μ ν•©ν•˜μ§€ μ•Šλ‹€.
  • λ˜ν•œ, κ°€μ€‘μΉ˜ 링크가 μ‘΄μž¬ν•˜λŠ” κ·Έλž˜ν”„μ˜ 경우 μ œλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•Šμ„ 수 μžˆλ‹€.

2.4 κ΅¬ν˜„ 방법

주둜 κ·Έλž˜ν”„κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, 경둜λ₯Ό μ°μ–΄μ£ΌλŠ” μ˜ˆμ œμ— ν™œμš©λœλ‹€. 0번 μ‹œμž‘ λ…Έλ“œλ₯Ό Queue에 λ„£κ³ , while λ°˜λ³΅λ¬Έμ„ 톡해 Queueκ°€ λΉ„μ›Œμ§ˆ λ•Œ κΉŒμ§€ νƒμƒ‰ν•œλ‹€.

λ˜ν•œ, 쀑볡이 λ°œμƒν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ boolean λ°°μ—΄ visitedλ₯Ό μ„ μ–Έν•˜μ—¬ 방문처리λ₯Ό κ΅¬ν˜„ν•œλ‹€.

# μ˜ˆμ‹œ κ·Έλž˜ν”„
graph = { 
	1 : [2,3,4], 
	2 : [5], 
	3 : [5], 
	4 : [], 
	5 : [6,7], 
	6 : [], 
	7 : [3]K
}
 
from collections import deque 
 
def BFS(root): 
	visited = [root] # ν˜„μž¬ λ…Έλ“œ λ°©λ¬Έ 처리 
	queue = deque([root]) 
	
	while queue: 
		v = queue.popleft() # νμ—μ„œ μ›μ†Œ κΊΌλ‚΄κΈ° 
		for w in graph[v]: 
			if w not in visited: 
				visited.append(w) 
				queue.append(w) 
	return visited
 
print(BFS(1)) #[1,2,3,4,5,6,7]

μ°Έκ³ μ‚¬μ΄νŠΈ