CS/알고리즘
[알고리즘] 그래프 탐색 01_DFS(깊이 우선 탐색)/BFS(너비 우선 탐색)
하루살이
2022. 1. 23. 02:22
DFS (깊이 우선 탐색, Depth First Search)
- 루트 노드(최상위)부터 리프 노드(최하위)까지 탐색한 후, 다시 올라와서 내려가는 방식(깊은 부분을 우선으로 탐색)
- 재귀(Recursion) 함수를 활용할 수 있음
- 스택(Stack)을 활용할 수 있음
동작 과정
1. 탐색 시작 노드를 스택에 삽입하고 방문 처리 함
2. 스택의 최상단 노드에 방문하지 않은 인접한 노드가 하나라도 있으면 그 노드를 스택에 넣고 방문
3. 더 이상 2번의 과정을 수행할 수 없을 때 까지 반복
1) 재귀 구조로 구현
# DFS_재귀
def dfs_recursive(graph, start, visited=[]):
visited.append(start) # 방문한 노드 추가
for node in graph[start]:
if node not in visited: # 끝까지 갔을 때(깊이)
dfs_recursive(graph, node, visited) # 깊이 탐색
return visited
graph = {
1: [2,3,4],
2: [5],
3: [5],
4: [],
5: [6,7],
6: [],
7: [3],
}
print(dfs_recursive(graph,1))
>> [1, 2, 5, 6, 7, 3, 4]
2) 스택을 이용한 반복 구조로 구현
# 역순으로 방문
def dfs_iteration(graph, root):
# visited = 방문한 꼭지점들을 기록한 리스트
visited = []
# dfs는 stack, bfs는 queue개념을 이용한다.
stack = [root]
while (stack): # 스택에 남은것이 없을 때까지 반복
node = stack.pop() # node : 현재 방문하고 있는 꼭지점
# 현재 node가 방문한 적 없다 -> visited에 추가한다.
# 그리고 해당 node의 자식 node들을 stack에 추가한다.
if (node not in visited):
visited.append(node)
stack.extend(graph[node])
return visited
graph = {
1: [2,3,4],
2: [5],
3: [5],
4: [],
5: [6,7],
6: [],
7: [3],
}
print(dfs_iteration(graph,1))
>>[1, 4, 3, 5, 7, 6, 2]
BFS (너비 우선 탐색, Breadth First Search)
- 루트 노드(최상위)부터 한 단계씩 내려가면서 탐색하는 방식
- 가장 가까운 노드부터 우선적으로 탐색하는 알고리즘
- 큐(Queue)을 활용할 수 있음
- 재귀(Recursion) 함수를 활용할 수 없음
동작과정
1. 탐색 시작 노드를 큐에 삽입하고 방문처리 함
2. 큐에서 노드를 꺼낸 해당 노드의 인접노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고, 방문처리 함
3. 더 이상 2번의 과정을 수행할 수 없을때 까지 반복!!
# 너비 우선 탐색, deque
# BFS는 재귀로 돌아가지 않음(큐를 이용하여 반복 구현만 가능)
from collections import deque
def bfs_iteration(graph, root):
visited = [] # 방문한 노드
queue = deque([root]) # bfs는 queue 사용
while (queue): # queue에 남은 것이 없을 때까지
node = queue.pop() # 현재 방문하는 노드
# node를 방문한 적 없다 -> visited에 추가
# 해당 노드의 자식 노드들을 queue에 추가
if node not in visited:
visited.append(node)
queue.extendleft(graph[node])
return visited
graph = {
1: [2,3,4],
2: [5],
3: [5],
4: [],
5: [6,7],
6: [],
7: [3],
}
print(bfs_iteration(graph,1))
>> [1, 2, 3, 4, 5, 6, 7]