⚡ 한 줄 요약: 정점과 간선으로 복잡한 관계를 정의하는 그래프 자료구조의 두 가지 구현법을 익히고, 상황에 맞는 최적의 탐색 알고리즘(BFS, DFS)을 선택하는 기준을 세웁니다.
우리가 매일 사용하는 내비게이션의 빠른 길 찾기, SNS의 '알 수도 있는 친구' 추천, 심지어 우리가 작성하는 코드의 모듈 의존성까지, 세상의 모든 복잡한 관계는 '그래프'로 설명할 수 있습니다.
데이터를 단순히 저장하는 단계를 넘어, 데이터 사이의 관계를 어떻게 효율적으로 다루는지 알아봅니다.
🧐 Why:
🎯 Goal:
그래프는 우리가 사는 복잡한 세상을 코드로 옮겨놓은 것과 같습니다. 데이터가 단순히 나열된 것이 아니라, 서로 어떻게 '연결'되어 있는지가 핵심입니다.
구성 요소
주요 특징 및 활용
그래프의 종류
방향 그래프(Directed Graph)

무방향 그래프(Undirected Graph)

가중 그래프(Weighted Graph)

💡 비유로 이해하기
무방향 그래프는 서로 수락해야 맺어지는 '페이스북 친구'와 같고, 방향 그래프는 한쪽만 일방적으로 할 수 있는 '트위터 팔로워'와 같습니다.
여기에 각 도시 사이의 '실제 거리'를 숫자로 적어두면 가중 그래프가 되는 것이죠.
그래프 구현은 정점 간의 연결 관계를 메모리에 저장하는 방식에 따라 인접 행렬과 인접 리스트 두 가지로 나뉩니다.
그래프를 코드로 구현할 때는 효율성(시간과 공간)의 트레이드오프를 반드시 고려해야 합니다.
정의
특징
구현 예시 (Python)
INF = float('inf') # 연결되지 않은 경우 무한대 설정
graph = [
[0, 2, 4], # 1번 정점에서의 가중치
[2, 0, 3], # 2번 정점에서의 가중치
[4, 3, 0] # 3번 정점에서의 가중치
]
print(graph[1][2]) # 2번과 3번 정점 사이의 가중치 '3' 출력
정의
특징
구현 예시 (Python)
graph = {
1: [(2, 2), (3, 4)], # 1번과 연결된 (정점, 가중치)
2: [(1, 2), (3, 3)], # 2번과 연결된 노드들
3: [(1, 4), (2, 3)]
}
print(graph[2]) # 2번 정점과 연결된 모든 정보 출력
graph[A][B] 한 번이면 끝나기 때문에 조회 빈도와 데이터의 양 사이의 균형을 보는 눈이 필요합니다.그래프(또는 트리)에서 모든 노드를 탐색하는 알고리즘은 크게 두 갈래로 나뉩니다.
문제의 목적에 따라 어떤 '방향'으로 나아갈지가 핵심입니다.
너비 우선 탐색(BFS, Breadth-First Search)
깊이 우선 탐색(DFS, Depth-First Search)
[BFS 동작 과정]
[DFS 동작 과정]
BFS 구현
from collections import deque
def bfs(graph, start):
visited = set([start])
queue = deque([start])
while queue:
node = queue.popleft()
print(node, end=" ") # 방문한 노드 출력
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
DFS 구현 (재귀 방식)
def dfs(graph, node, visited=None):
if visited is None:
visited = set()
visited.add(node)
print(node, end=" ") # 방문한 노드 출력
for neighbor in graph[node]:
if neighbor not in visited:
dfs(graph, neighbor, visited)
[공통 그래프 정의 및 결과]
1: [2, 3], 2: [4], 3: [5], 4: [], 5: []1 2 3 4 5 (층별 탐색)1 2 4 3 5 (깊이 우선)💡 비유로 이해하기
BFS는 호수에 돌을 던졌을 때 동심원을 그리며 퍼져나가는 파동과 같고, DFS는 미로에서 한쪽 벽만 계속 짚으면서 막다른 길이 나올 때까지 가보는 탐색자와 같습니다.
그래프 구현 방식
| 구분 | 인접 행렬 | 인접 리스트 |
|---|---|---|
| 저장 방식 | 2차원 배열 (graph[i][j]) | 연결 리스트 또는 딕셔너리 |
| 공간 복잡도 | (간선 수에 비례) | |
| 조회 성능 | (연결 여부 즉시 확인) | (리스트를 순회해야 함) |
| 추천 상황 | 간선이 매우 많은 밀집 그래프 | 간선이 적은 희소 그래프 |
탐색 알고리즘
| 구분 | BFS(너비 우선 탐색) | DFS(깊이 우선 탐색) |
|---|---|---|
| 사용 자료구조 | 큐(Queue) | 스택(Stack) 또는 재귀 |
| 탐색 특징 | 시작점 기준 가까운 노드부터 | 한 경로를 끝까지 파고든 후 복귀 |
| 주요 활용 | 최단 경로 찾기, 최단 거리 보장 | 모든 경우의 수 탐색, 사이클 확인 |
| 비유 | 호수의 파동 | 미로 찾기 |