목차
반응형
1. 그래프의 구성
그래프는 노드(Node)와 노드를 연결하는 간선(Edge)으로 구성됩니다.
- 노드(Node): 그래프 내에서 개별적인 데이터
- 간선(Edge): 노드 간의 관계나 경로
2. 그래프의 종류
2.1. 방향 그래프(Directed Graph, Digraph)
- 간선에 방향이 있어서 한 노드에서 다른 노드로의 일방향 경로만을 나타냅니다.
- defaultdict란?
- 존재하지 않는 키를 조회할 때 KeyError를 발생시키는 대신, 기본값을 반환하도록 할 수 있습니다.
- 키가 존재하지 않으면 기본값으로 초기화된 후 사용
from collections import defaultdict
class DirectedGraph:
def __init__(self):
# defaultdict를 사용하여 인접 리스트로 그래프를 표현
self.graph = defaultdict(list)
# 노드와 노드 사이에 간선을 추가하는 메소드
def add_edge(self, u, v):
self.graph[u].append(v)
# 그래프를 출력하는 메소드
def print_graph(self):
for node in self.graph:
print(f"{node} -> {', '.join(map(str, self.graph[node]))}")
# 그래프 생성 및 간선 추가
graph = DirectedGraph()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 0)
graph.add_edge(2, 3)
graph.add_edge(3, 3)
# 그래프 출력
graph.print_graph()
출력 결과
0 -> 1, 2
1 -> 2
2 -> 0, 3
3 -> 3
2.2. 무방향 그래프(Undirected Graph)
- 간선에 방향이 없어서 노드 간의 관계가 양방향으로 자유롭게 이동할 수 있습니다.
from collections import defaultdict
class UndirectedGraph:
def __init__(self):
# defaultdict를 사용하여 인접 리스트로 그래프를 표현
self.graph = defaultdict(list)
# 노드와 노드 사이에 간선을 추가하는 메소드
def add_edge(self, u, v):
self.graph[u].append(v)
self.graph[v].append(u)
# 그래프를 출력하는 메소드
def print_graph(self):
for node in self.graph:
print(f"{node} -> {', '.join(map(str, self.graph[node]))}")
# 그래프 생성 및 간선 추가
graph = UndirectedGraph()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 3)
# 그래프 출력
graph.print_graph()
출력 결과
0 -> 1, 2
1 -> 0, 2
2 -> 0, 1, 3
3 -> 2
3. 그래프 탐색
3.1. 깊이 우선 탐색 (DFS)
- 재귀적 구현
from collections import defaultdict
class Graph:
def __init__(self):
self.graph = defaultdict(list)
def add_edge(self, u, v):
self.graph[u].append(v)
def dfs_recursive(self, start_node):
visited = set()
self._dfs_recursive_helper(start_node, visited)
def _dfs_recursive_helper(self, node, visited):
visited.add(node)
print(node, end=' ')
for neighbor in self.graph[node]:
if neighbor not in visited:
self._dfs_recursive_helper(neighbor, visited)
# 그래프 생성 및 간선 추가
graph = Graph()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 0)
graph.add_edge(2, 3)
graph.add_edge(3, 3)
# DFS 실행
print("DFS (재귀)를 시작 노드 2에서 수행:")
graph.dfs_recursive(2) # Output: 2 0 1 3
- 스택을 이용한 비재귀적 구현
class Graph:
def __init__(self):
self.graph = defaultdict(list)
def add_edge(self, u, v):
self.graph[u].append(v)
def dfs_stack(self, start_node):
visited = set()
stack = [start_node]
while stack:
node = stack.pop()
if node not in visited:
print(node, end=' ')
visited.add(node)
for neighbor in reversed(self.graph[node]):
if neighbor not in visited:
stack.append(neighbor)
# 그래프 생성 및 간선 추가
graph = Graph()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 0)
graph.add_edge(2, 3)
graph.add_edge(3, 3)
# DFS 실행
print("\nDFS (스택)를 시작 노드 2에서 수행:")
graph.dfs_stack(2) # Output: 2 3 0 1
3.2. 너비 우선 탐색 (BFS)
큐를 이용한 구현.
from collections import defaultdict, deque
class Graph:
def __init__(self):
self.graph = defaultdict(list)
def add_edge(self, u, v):
self.graph[u].append(v)
def bfs(self, start_node):
visited = set()
queue = deque([start_node])
visited.add(start_node)
while queue:
node = queue.popleft()
print(node, end=' ')
for neighbor in self.graph[node]:
if neighbor not in visited:
queue.append(neighbor)
visited.add(neighbor)
# 그래프 생성 및 간선 추가
graph = Graph()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 0)
graph.add_edge(2, 3)
graph.add_edge(3, 3)
# BFS 실행
print("BFS를 시작 노드 2에서 수행:")
graph.bfs(2) # Output: 2 0 3 1
4. 그래프 표현 방법
- 인접 행렬(Adjacency Matrix): 2차원 배열을 사용하여 그래프를 표현
- 인접 리스트(Adjacency List): 리스트 배열을 사용하여 각 노드의 이웃 노드들을 저장
- 엣지 리스트(Edge List): 간선들을 리스트로 나열하여 그래프를 표현
5. 최단 경로 알고리즘
- 다익스트라 알고리즘(Dijkstra's Algorithm): 하나의 정점에서 모든 다른 정점으로의 최단 경로를 찾습니다.
- 벨만-포드 알고리즘(Bellman-Ford Algorithm): 음수 가중치가 있는 그래프에서 최단 경로를 찾을 수 있습니다.
- 플로이드-와샬 알고리즘(Floyd-Warshall Algorithm): 모든 정점 간의 최단 경로를 찾습니다.
6. 최소 신장 트리 알고리즘(Minimum Spanning Tree)
- 크루스칼 알고리즘(Kruskal's Algorithm): 간선을 오름차순으로 정렬한 뒤, 최소 비용 신장 트리를 구성합니다.
- 프림 알고리즘(Prim's Algorithm): 정점을 하나씩 추가하여 최소 비용 신장 트리를 구성합니다.
7. 기타 유용한 알고리즘 및 개념
- 위상 정렬(Topological Sort): 방향 그래프에서 노드의 선후 관계를 정렬합니다.
- 강한 연결 요소(Strongly Connected Components): 방향 그래프에서 서로 도달 가능한 노드 집합을 찾습니다.
- 양방향 탐색(Bidirectional Search): 출발 노드와 목표 노드 양쪽에서 동시에 탐색을 수행하여 효율성을 높입니다.
반응형
'파이썬 > 코딩테스트' 카테고리의 다른 글
[알고리즘] 정렬 (버블, 선택, 삽입, 병합, 퀵) (0) | 2024.05.21 |
---|---|
[자료구조] 트리 (0) | 2024.05.17 |
[자료구조] 스택(Stack) 큐(Queue) 해시테이블(Hash Table) (0) | 2024.04.29 |
[자료구조] 문자열 (파이썬) (0) | 2024.04.20 |
[자료구조] 배열 (파이썬이에서는 리스트) (1) | 2024.04.20 |