1. 그래프 탐색이란?
그래프 탐색(graph search)
- 하나의 노드에서 시작하여 connected graph를 순회하는 것
그래프 탐색 종류
BFS(Breadth First Search)
DFS(Depth First Search)
2. BFS(Breadth First Search)
BFS
- 시작 정점에서 시작하여 너비 우선 순서로 그래프의 모든 정점을 탐색하는 그래프 통과 알고리즘
- 다음 레벨의 정점들을 탐색하기 전에 현재 레벨의 정점들을 모두 탐색한다.
BFS 알고리즘
- 모든 노드를 방문하지 않은 노드로 표시한다.
- 시작 노드를 방문 표시 후, 큐에 넣는다.
- 큐 가장 앞 노드를 꺼낸다.
- 꺼낸 노드에 인접한 노드에 접근한다.
- 처음 방문한 노드면 방문한 노드 표시를 해주고 큐에 넣는다.
- 꺼낸 노드에 인접한 노드를 전부 접근하기 전까지 4단계로 돌아간다.
- 큐에 아무 노드가 없을 때까지 3단계로 돌아간다.
from collections import deque
class StationNode:
"""지하철 역을 나타내는 역"""
def __init__(self, station_name):
self.station_name = station_name
self.adjacent_stations = []
self.visited = False
def add_connection(self, station):
"""파라미터로 받은 역과 엣지를 만들어주는 메소드"""
self.adjacent_stations.append(station)
station.adjacent_stations.append(self)
def create_station_graph(input_file):
stations = {}
with open(input_file) as stations_raw_file:
for line in stations_raw_file:
previous_station = None
raw_data = line.strip().split("-")
for name in raw_data:
station_name = name.strip()
if station_name not in stations:
current_station = StationNode(station_name)
stations[station_name] = current_station
else:
current_station = stations[station_name]
if previous_station is not None:
current_station.add_connection(previous_station)
previous_station = current_station
return stations
def bfs(graph, start_node):
"""시작 노드에서 bfs를 실행하는 함수"""
queue = deque()
for station_node in graph.values():
station_node.visited = False
start_node.visited = True
queue.append(start_node)
while queue:
current_station = queue.popleft()
for neighbor in current_station.adjacent_stations:
if not neighbor.visited:
neighbor.visited = True
queue.append(neighbor)
stations = create_station_graph("./new_stations.txt")
gangnam_station = stations["강남"]
bfs(stations, gangnam_station)
print(stations["강동구청"].visited)
print(stations["평촌"].visited)
print(stations["송도"].visited)
print(stations["개화산"].visited)
print(stations["반석"].visited)
print(stations["지족"].visited)
print(stations["노은"].visited)
print(stations["(대전)신흥"].visited)
True
True
True
True
False
False
False
False
BFS 알고리즘 시간 복잡도 분석
- 모든 노드를 방문하지 않은 노드로 표시한다. (BFS 노드 전처리)
- Worst-case time complexity: O(V)
- Best-case time complexity: O(V)
- Average time complexity: O(V)
- 시작 노드를 방문 표시 후, 큐에 넣는다. (O(1))
- 큐 가장 앞 노드를 꺼낸다. (O(1))
- 꺼낸 노드에 인접한 노드에 접근한다. (O(1))
- 처음 방문한 노드면 방문한 노드 표시를 해주고 큐에 넣는다. (O(1))
- 꺼낸 노드에 인접한 노드를 전부 접근하기 전까지 3단계로 돌아간다.
- Worst-case time complexity: O(V)
- Best-case time complexity: O(1)
- Average time complexity: O(Eaj)
- 큐에 아무 노드가 없을 때까지 2단계로 돌아간다.
- Worst-case time complexity: O(V)
- Best-case time complexity: O(1)
- Average time complexity: O(V)
- BFS 알고리즘 시간 복잡도
- Worst-case time complexity: O(V^2)
- Best-case time complexity: O(1)
- Average time complexity: O(V+E)
3. DFS(Depth First Search)
DFS
- 시작 정점에서 시작하여 backtracking하기 전에 각 분기를 따라 가능한 한 깊은 레벨까지 탐색하는 그래프 통과 알고리즘
- 다음 줄의 정점들을 탐색하기 전에 현재 줄의 모든 레벨에 있는 정점들을 모두 탐색한다.
DFS 알고리즘
- 방문한 노드에 현재 스택에 들어있는지에 대한 정보도 추가해야한다.
- 모든 노드를 방문하지 않은 노드로 표시한다.
- 시작 노드를 스택에 넣은 노드로 표시해주고, 스택에 넣는다.
- 스택 가장 위 노드를 꺼내고 스택에서 꺼낸 노드로 표시한다.
- 꺼낸 노드에 인접한 노드에 접근한다.
- 처음 방문한 노드면 스택에 넣은 노드로 표시해주고 스택에 넣는다.
- 꺼낸 노드에 인접한 노드를 전부 접근하기 전까지 4단계로 돌아간다.
- 스택에 노드가 있다면 3단계로 돌아간다.
def dfs(graph, start_node):
"""dfs 함수"""
stack = deque()
for station_node in graph.values():
station_node.visited = 0
start_node.visited = 1
stack.append(start_node)
while stack:
current_node = stack.pop()
current_node.visited = 2
for neighbor in current_node.adjacent_stations:
if neighbor.visited == 0:
neighbor.visited = 1
stack.append(neighbor)
DFS 알고리즘 시간 복잡도 분석
- 모든 노드를 방문하지 않은 노드로 표시한다.
- Worst-case time complexity: O(V)
- Best-case time complexity: O(V)
- Average time complexity: O(V)
- 시작 노드를 스택에 넣은 노드로 표시해주고, 스택에 넣는다. (O(1))
- 스택 가장 위 노드를 꺼내고 스택에서 꺼낸 노드로 표시한다. (O(1))
- 꺼낸 노드에 인접한 노드에 접근한다. (O(1))
- 처음 방문한 노드면 스택에 넣은 노드로 표시해주고 스택에 넣는다. (O(1))
- 꺼낸 노드에 인접한 노드를 전부 접근하기 전까지 4단계로 돌아간다.
- Worst-case time complexity: O(V)
- Best-case time complexity: O(1)
- Average time complexity: O(Eaj)
- 스택에 노드가 있다면 3단계로 돌아간다.
- Worst-case time complexity: O(V)
- Best-case time complexity: O(1)
- Average time complexity: O(V)
- BFS 알고리즘 시간 복잡도
- Worst-case time complexity: O(V^2)
- Best-case time complexity: O(1)
- Average time complexity: O(V+E)
Feedback
- BFS. DFS의 시간, 공간 복잡도를 분석해보자.
- 언어별로 그래프 탐색을 구현해보자.
- 추상 자료형은 그래프 탐색을 어떻게 구현했는지 찾아보자.
참고 자료