일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 백준
- 코테공부
- 소수 판정
- 이코테
- 논문리뷰
- #이코테2021
- 파이썬 머신러닝 완벽가이드 공부
- BruteForchSearch
- BruteForceSearch
- Graph Representation Learning
- #나동빈
- zerodivide
- 유클리드 호제법
- 글또8기
- 그래프란
- 데이콘 필사
- numpy
- graph
- 나동빈
- 추천시스템
- 추천시스템 입문
- 수학
- 에스토스테네스의 체
- paper review
- 질문 정리
- CS224W
- 강의정리
- allow_pickle
- 알고리즘
- nan값
- Today
- Total
꾸준히 써보는 공부 기록
DFS/BFS 본문
탐색 (Search)
많은 양의 데이터 중에서 원하는 데이터를 찾는 과정을 의미. 대표적인 탐색 알고리즘으로 DFS, BFS.
자료 구조
‘데이터를 표현하고 관리하고 처리하기 위한 구조’를 의미. 그 중 스택과 큐는 자료구조의 기초 개념으로 pop과 push로 이루어져 있다.
스택 (Stack)
박스 쌓기 !! FILO 구조이다 (First In Last Out) !!
삽입 순서 : a - b - c 삭제 순서 : c - b - a
stack = []
stack.append(a)
stack.pop()
파이썬의 경우, 기본 리스트에서 append( )와 pop( ) 메서드를 이용.
큐 (Queue)
대기줄 !! FIFO 구조이다 (First In First Out) !!
삽입 순서 : a - b - c 삭제 순서 : a - b - c
from collections import deque
queue = deque()
queue.append(5)
queue.popleft()
# 출력을 위해 역순으로 바꾸기 # 나중에 들어온 원소부터 출력하기 위해서
queue.reverse()
print(queue)
넣고 빼는 속도가 리스트 자료형에 비해 효율적이고 간단하다. 리스트 자료형으로 변경하기 위해서 list( ) 메소드를 이용한다.
재귀 함수 (Recursive Function)
자기 자신을 다시 호출하는 함수. 컴퓨터 내부에서 재귀 함수의 수행은 스택 자료구조를 이용한다. 연속해서 호출되는 함수는 메인 메모리의 스택 공간에 적재되기 때문에 !!
예시 : DFS 수학의 점화식(재귀식)을 그대로 소스코드로 옮긴 형태이다. 수학에서 점화식은 특정한 함수를 자신보다 더 작은 변수에 대한 함수와의 관계로 표현한 것을 의미한다. 종료 조건이 중요 !!
DFS
깊이 우선 탐색. 그래프에서 깊은 부분을 우선적으로 탐색하는 알고리즘.
- 인접 행렬(Adjacency Matrix) 방식은 2차원 배열에 각 노드가 연결된 형태를 기록하는 방식.
- INF = 999999999 graph = [[0, 7, 5], [7, 0, INF], [5, INF, 0]]
- 인접 리스트(Adjacency List) 방식은 모든 노드에 연결된 노드에 대한 정보를 차례대로 연결되어 저장. ‘연결 리스트’라는 자료구조를 이용해 구현. 파이썬은 기본 자료형인 리스트 자료형을 활용.
- graph = [[] for _ in range(3)] graph[0].append((1,7))
DFS는 스택 자료구조를 이용하며 구체적인 동작 과정은 다음과 같다.
- 탐색 시작 노드를 스택에 삽입하고 방문 처리.
- 스택의 최상단 노드에 방문하지 않은 인접 노드가 있으면 그 인접 노드를 스택에 넣고 방문처리. 방문하지 않은 인접 노드가 없으면 스택에서 최상단 노드를 꺼낸다.
- 2)번의 과정을 더 이상 수행할 수 없을 때까지 반복.
데이터의 개수가 N개인 경우, O(N)의 시간이 소요된다.
def dfs(graph, v, visited):
# 현재 노드를 방문 처리
visited[v] = True
for i in graph[v]:
if not visited[i]:
dfs(graph, i, visited)
graph = [[],[2,3,8],[1,7],[1,4,5],[3,5],[3,4],[7],[2,6,8],[1,7]]
visited = [False] * 9
dfs(graph, 1, visited)
BFS
너비 우선 탐색. 가까운 노드부터 탐색하는 알고리즘. 선입선출 방식인 큐 자료구조를 이용하는 것이 정석이다. 인접한 노드를 반복적으로 큐에 넣도록 알고리즘을 작성하면 자연스럽게 먼저 들어온 것이 먼저 나가게 됨.
- 탐색 시작 노드를 큐에 삽입하고 방문 처리를 한다.
- 큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리를 한다.
- 2)번의 과정을 더 이상 수행할 수 없을 때까지 반복.
데이터의 개수가 N개인 경우, O(N)의 시간이 소요된다. 일반적인 수행 시간은 DFS보다 좋은 편!
from collections import deque
def bfs(graph, start, visited):
queue = deque([start])
visited[start] = True
while queue:
v = queue.popleft()
for i in graph[v]:
if not visited[i]:
queue.append(i)
visited[i] = True
graph = [[],[2,3,8],[1,7],[1,4,5],[3,5],[3,4],[7],[2,6,8],[1,7]]
visited = [False]*9
bfs(graph, 1, visited)