22gamin
탐색 알고리즘 DFS/BFS 본문
탐색이란
많은 양의 데이터 중에서 원하는 데이터를 찾는 과정을 의미한다.
그래프,트리 등의 자료구조 안에서 탐색을 하는 문제로 자주 다룸
-> 대표적인 알고리즘으로 DFS와 BFS를 꼽을 수 있다
이를 학습하기 위해서는 기본 자료구조인 스택과 큐를 이해해야 한다.
스택
- 스택은 박스 쌓기에 비유할 수 있다.
- 아래에서부터 위로 차곡차곡 쌓기 때문에 아래에 있는 박스를 치우려면 위에 있는 박스를 먼저 내려야 한다.
- 이러한 구조를 선입후출(First In Last Out) 구조 또는 후입선출(Last In First Out) 구조라고 한다.
- 파이썬에서 스택을 사용할 때는 별도의 라이브러리를 사용할 필요 없이 기본 리스트에서 append()와 pop() 메서드를 이용한다.
- append()는 리스트 가장 뒤쪽에 데이터 삽입
- pop()은 리스트 가장 뒤쪽에서 데이터 제거
큐
- 큐에는 대기 줄에 비유할 수 있다.
- 줄을 먼저 선 사람이 먼저 들어가고, 나중에 온 사람일수록 나중에 들어간다.
- 선입선출(First In First Out)구조라고 한다.
- 삭제는 앞에 있는 것부터 삭제, 삽입은 뒤로
- 파이썬으로 큐를 구현할 때는 collections 모듈에서 제공하는 deque 자료 구조를 활용해야한다.
- from collections import deque
재귀함수
- 자기 자신을 다시 호출하는 함수이다.
- 컴퓨터 내부에서 재귀 함수의 수행은 스택 자료 구조를 이용한다. 함수를 계속 호출했을 때 가장 마지막에 호출한 함수가 먼저 수행을 끝내야 그 앞의 함수 호출이 종료되기 때문이다.
- DFS에서 자주 이용됨
DFS
- Depth-First Search, 깊이 우선 탐색이라고도 부르며 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘이다.
- 최대한 멀리 있는 노드를 우선으로 탐색하는 방식
1. 탐색 시작 노드를 스택에 삽입하고 방문 처리를 한다.
2. 스택의 최상단 노드에 방문하지 않은 인접 노드가 있으면 그 인접 노드를 스택에 넣고 방문 처리를 한다. 방문하지 않은 인접 노드가 없으면 스택에서 최상단 노드를 꺼낸다.
3. 2.번의 과정을 더 이상 수행할 수 없을 때까지 반복한다.
DFS 예제
# dfs
def dfs(graph, v, vistied):
#현재 노드를 방문 처리
vistied[v] = True
print(v, end=' ')
#현재 노드와 연결된 다른 노드를 재귀적으로 방문
for i in graph[v]:
if not vistied[i]:
dfs(graph, i, vistied)
- 스택 자료구조에 기초한다.
- 데이터 개수가 N개인 경우 O(N)의 시간이 소요된다.
- 스택을 이용하는 알고리즘이기 때문에 실제 구현은 재귀함수를 이용했을 때 매우 간결하게 구현할 수 있다.
BFS
- Breadth First Search, 너비 우선 탐색 이라고 부르며 가까운 노드부터 탐색하는 알고리즘이다.
- BFS 구현은 선입선출 방식인 큐 자료 구조를 이용한다.
- 인접한 노드를 반복적으로 큐에 넣도록 알고리즘을 작성하면 자연스럽게 먼저 들어온 것이 먼저 나가게 되어, 가까운 노드부터 탐색을 진행하게 된다.
1. 탐색 시작 노드를 큐에 삽입하고 방문 처리를 한다.
2. 큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리를 한다.
3. 2.번의 과정을 더 이상 수행할 수 없을 때까지 반복한다.
BFS 예제
from collections import deque
def bfs(graph, start, visited):
#큐 구현을 위해 deque 라이브러리 사용
queue = deque([start])
#현재 노드를 방문 처리
visited[start] = True
#큐가 빌 때까지 반복
while queue:
#큐에서 하나의 원소를 뽑아 출력
v = queue.popleft()
print(v, end=' ')
#해당 원소와 연결된, 아직 방문하지 않은 원소들을 큐에 삽입
for i in graph[v]:
if not visited[i]:
queue.append(i)
visited[i] = True
- 큐 자료 구조에 기초한다.
- deque 라이브러리를 사용하는 것이 좋으며 탐색을 수행함에 있어 O(N)의 시간이 소요된다.
- 일반적인 경우 실제 수행 시간은 DFS보다 좋은 편이다.
코딩 테스트 중 2차원 배열에서의 탐색 문제를 만나면 이렇게 그래프 형태로 바꿔서 생각하면 풀이 방법을 조금 더 쉽게 떠올릴 수 있다.
'알고리즘' 카테고리의 다른 글
[Java] Scanner vs BufferedReader (1) | 2024.09.10 |
---|---|
deque의 이해 및 사용법 (0) | 2024.05.09 |
음료수 얼려 먹기/미로 탈출 [DFS/BFS] (0) | 2024.01.31 |