탐색 (Search)
탐색이란 많은 양의 데이터 중에서 원하는 데이터를 찾는 과정을 의미한다.
대표적인 탐색 알고리즘으로는 DFS, BFS 가 존재하는데, 이를 이해하기 위해서는 스택, 큐, 재귀함수를 알아야 한다.
참고
2021.05.27 - [자료구조] - [자료구조] 자료구조 기초 : 스택 / 큐 / 재귀함수
참고
2021.05.27 - [자료구조] - [자료구조] 그래프 (Graph)
DFS (Depth - First Search, 깊이 우선 탐색)
DFS 는 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘이다.
즉, 특정한 경로로 탐색하다가 특정한 상황에서 최대한 깊숙이 들어가서 노드를 방문한 후, 다시 돌아가 다른 경로로 탐색하는 알고리즘이다. → 스택 자료구조 이용
SW Expert Academy 홈페이지 강의를 참고하면 좋다.
메인 페이지 > Learn > Programming Intermediate > Stack1 > 5차시 DFS
https://swexpertacademy.com/main/learn/course/subjectList.do?courseId=AVuPDN86AAXw5UW6
DFS 동작 과정
- 탐색 시작 노드를 스택에 삽입하고 방문 처리를 한다. 방문 처리는 스택에 한 번 삽입되어 처리된 노드가 다시 스택에 삽입되지 않도록 체크하는 것을 의미한다. 방문 처리를 함으로써 각 노드를 한 번씩만 처리할 수 있다.
- 스택의 최상단 노드(가장 마지막에 방문한 노드)에 방문하지 않은 인접 노드(연결된 노드)가 있으면, 그 인접 노드를 스택에 넣고 방문 처리를 한다. 방문하지 않은 인접 노드가 없으면 스택에서 최상단 노드를 꺼낸다. (최상단 노드에 연결된 노드를 모두 방문했기 때문)
- 2번의 과정을 더 이상 수행할 수 없을 때까지 반복한다. (스택이 빌 때까지)
DFS 특징
스택 자료구조에 기초한다는 점에서 구현이 간단하다.
실제로는 스택을 쓰지 않아도 되며, 탐색을 수행함에 있어서 데이터의 개수가 N개인 경우 O(N)의 시간이 소요된다.
실제 구현은 재귀 함수를 이용했을 때 매우 간결하게 구현할 수 있다.
코드 예제
# DFS 메서드 정의
def DFS(graph, v, visited) :
# 현재 노드를 방문 처리
visited[v] = True
print(v, end = ' ')
# 현재 노드와 연결된 다른 노드를 재귀적으로 방문
for i in graph[v] :
if not visited[i] :
DFS(graph, i, visited)
# 각 노드가 연결된 정보를 리스트 자료형으로 표현 (2차원 리스트)
graph = [
[],
[2, 3, 8], # 노드 1에 연결된 노드들
[1, 7],
[1, 4, 5],
[3, 5],
[3, 4],
[7],
[2, 6, 8],
[1, 7]
]
# 각 노드가 방문된 정보를 리스트 자료형으로 표현 (1차원 리스트)
visited = [False] * 9
# 정의된 DFS 함수 호출
DFS(graph, 1, visited)
# 결과 : 노드의 방문(탐색) 순서
1 2 7 6 8 3 4 5
BFS (Breadth First Search, 너비 우선 탐색)
BFS 는 가까운 노드부터 탐색하는 알고리즘이다.
BFS 구현에서는 선입선출 방식인 큐 자료구조를 이용하는 것이 정석이다.
BFS 동작 과정
- 탐색 시작 노드를 큐에 삽입하고 방문 처리를 한다.
- 큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리를 한다.
- 2번의 과정을 더 이상 수행할 수 없을 때까지 반복한다.
BFS 특징
큐 자료구조에 기초한다는 점에서 구현이 간단하다.
실제 구현은 deque 라이브러리를 이용하는 것이 좋으며, 탐색을 수행함에 있어서 O(N)의 시간이 소요된다.
일반적인 경우, 실제 수행 시간은 DFS 보다 좋은 편이다.
코드 예제
from collections import deque
# BFS 메서드 정의
def BFS(graph, start, visited):
# 큐(queue) 구현을 위해 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
# 각 노드가 연결된 정보를 리스트 자료형으로 표현 (2차원 리스트)
graph = [
[],
[2, 3, 8],
[1, 7],
[1, 4, 5],
[3, 5],
[3, 4],
[7],
[2, 6, 8],
[1, 7]
]
# 각 노드가 방문된 정보를 리스트 자료형으로 표현 (1차원 리스트)
visited = [False] * 9
# 정의된 BFS 함수 호출
BFS(graph, 1, visited)
# 결과 : 노드의 방문(탐색) 순서
1 2 3 8 7 4 5 6
출처
나동빈, 『이것이 취업을 위한 코딩테스트다 with 파이썬』, 한빛미디어(주), 2020년
'자료구조 알고리즘' 카테고리의 다른 글
[알고리즘] Greedy Algorithm 탐욕 알고리즘 / 파이썬 (0) | 2021.07.13 |
---|---|
[자료구조 알고리즘] 순차 탐색 / 이진 탐색 / 트리(Tree) / 이진 탐색 트리 (0) | 2021.06.23 |
[알고리즘] 정렬 (Sorting) / 코드 Python / 선택정렬, 삽입정렬, 퀵정렬, 계수정렬 (0) | 2021.06.15 |
[자료구조] 그래프 (Graph) (0) | 2021.05.27 |
[자료구조] 자료구조 기초 : 스택 / 큐 / 재귀함수 (0) | 2021.05.27 |