0. 들어가기 전에
- 그래프 : 정점(node)과 간선(edge)으로 이루어진 자료 구조
- 그래프 탐색 : 하나의 정점으로부터 시작하여 차례대로 모든 정점들을 한 번씩 방문하는 것
- DFS, BFS 모두 그래프 탐색의 일종
- DFS, BFS는 target을 찾거나, 방문 경로를 출력하기에 활용
1. DFS (Depth First Search, 깊이 우선 탐색)
- 최대한 깊이 내려간 뒤, 더 깊이 갈 곳이 없을 때 옆으로 이동
= 하나의 node에서 시작하여 다음 분기(branch)로 넘어가기 전에 해당 분기를 완벽하게 탐색
- 특징
= 모든 노드를 방문하고자 할 때 사용
= BFS에 비해 간단하나, 검색 속도는 느림
2. BFS (Breadth First Search, 너비 우선 탐색)
- 최대한 넓게 이동한 뒤, 더 이상 갈 곳이 없을 때 아래로 이동
= 하나의 node에서 인접한 node를 먼저 탐색
- 특징
= 두 node 사이의 최단 경로를 찾을 때 사용
3. 구현
graph = {
'A': ['B'],
'B': ['A', 'C', 'H'],
'C': ['B', 'D'],
'D': ['C', 'E', 'G'],
'E': ['D', 'F'],
'F': ['E'],
'G': ['D'],
'H': ['B', 'I', 'J', 'M'],
'I': ['H'],
'J': ['H', 'K'],
'K': ['J', 'L'],
'L': ['K'],
'M': ['H']
}
1. DFS
def dfs(graph, root):
visited = []
stack = []
stack.append(root)
while stack:
node = stack.pop()
if node not in visited:
visited.append(node)
queue.extend(graph[node])
return visited
def dfs(root):
stack = [root]
while True:
if len(stack) == 0:
print('All node searched.')
return None
node = stack.pop()
if node == Target:
print('Target found.')
return node
stack.extend(children)
def dfs(graph, start, visited=[]):
visited.append(start)
for node in graph[start]:
if node not in visited:
dfs(graph, node, visited)
return visited
2. BFS
def bfs(graph, root):
visited = []
queue = []
queue.append(root)
while queue:
node = queue.pop(0)
if node not in visited:
visited.append(node)
queue.extend(graph[node])
return visited
def bfs(root):
queue = [root]
while True:
if len(queue) == 0:
print('All node searched.')
return None
node = queue.pop(0)
if node == Target:
print('Target found.')
return node
queue.extend(children)
from collections import deque
def bfs(graph, root):
visited = []
queue = deque()
queue.append(root)
while queue:
node = queue.popleft()
if node not in visited:
visited.append(node)
queue.extend(graph[node])
return visited
4. 시간 복잡도
5. 문제 응용
- 모든 노드 방문 : DFS, BFS
- 경로의 특징(조건)을 저장해야 함 : DFS
- 최단거리 찾기 : BFS