💡 그래프란, 정점과 정점을 연결하는 간선으로 이루어진 자료구조이고 아래는 그래프의 탐색 방법이다.
깊이 우선 탐색으로, 루트 노드(or 임의의 노드)에서 시작하여 왼쪽이나 오른쪽부터 다음 분기(branch)로 넘어가기전에 해당 분기를 완벽하게(최대한의 깊이로) 탐색하는 방식이다.
# DFS - 재귀호출 구현
# 방문한 내용이 초기화되지 않게 인자로 넘겨주는 것이다.
def dfs_recursive(start_v, visited):
visited.append(start_v)
for adj in graph[start_v]:
if adj not in visited:
# 해당 재귀호출에서 업데이트된 visited를 다시 인자로 넘겨준다.
dfs_recursive(adj, visited)
return visited
# [1, 2, 5, 6, 7, 3, 4] 재귀호출 결과
# DFS - 스택으로 구현
def dfs_stack(start_v):
visited = []
# 방문할 순서를 담아두는 용도
stack = [start_v]
while stack:
# 제일 최근에 삽입된 노드를 꺼내고 방문처리 한다.
top_v = stack.pop()
visited.append(top_v)
# 인접 노드가 visited에 stack에 쌓고 계속 반복문이 돌게 만들어준다.
for adj in graph[top_v]:
if adj not in visited:
stack.append(adj)
return visited
# [1, 4, 3, 5, 7, 6, 2] 스택 결과
너비 우선 탐색으로, 루트 노드(or 임의의 노드)에서 시작하여 현재 정점에 인접한 노드를 먼저 탐색하는 방식이다.
from collections import deque
# BFS - deque를 이용하여 큐로 구현
def bfs_queue(start):
# 시작 노드를 방문 처리한다.
visited = [start]
# 큐를 만들고 시작 노드를 담아준다.
q = deque([start])
# 큐가 빌 때까지 반복된다.
while q:
node = q.popleft()
for adj in graph[node]:
# 인접 노드가 방문하지 않은곳이라면, 방문 처리와 큐에 쌓아준다.
if adj not in visited:
q.append(adj)
visited.append(adj)
return visited
# [1, 2, 3, 4, 5, 6, 7] BFS 결과물이다.
DFS와 BFS를 처음 마주하고 이게 진짜 알고리즘이구나 느꼈던 한 주 였다.
처음에는 개념을 이해하고 예시를 본 뒤 문제를 풀어보고 있었는데 이렇게 하는거는 현재로서는 큰 의미가 없겠구나 깨닫고 방향을 틀어서 문제의 답을 보고 이해라도 제대로 하고 넘어가는게 이번주의 목표가 되었다.
그러다 집중력이 한계에 달했을 때, 내 주력 언어인 JavaScript를 한번 둘러보았는데 여기서 또 충격을 받게 되었다.
JS는 내 주력 언어인데 잠깐 파이썬을 몇주 사용하였다고 JS파일에서 파이썬 문법을 쓰고있는 나를 보게되었고, 되돌아보니 배우기만 하고 정작 내 손으로 코드를 많이 작성해보지 않았다는것을 깨달았다.
앞으로 남은 알고리즘 기간 동안 알고리즘과 주력 언어의 부가적인 공부시간을 잘 분배해서 사용해야 될 것 같다.