일반적으로 간선의 특성에 따라서 그래프의 종류가 구분됩니다.
간선이 가중치(Weight)를 갖는 그래프입니다.
이 값은 간선 사이의 "비용", "길이", "거리" 등 다양한 것을 나타낼 수 있습니다.
무방향 가중 그래프 (Undirected Weighted Graph) = 무방향 그래프 + 가중치
방향 가중 그래프 (Directed Weighted Graph) = 방향 그래프 + 가중치
일반적으로 방향 가중 그래프를 네트워크(Network)라고 부른다.
가중 그래프는 노드 사이의 연결 관계에 추가로 비용 혹은 거리 등의 추가 속성을 정의할 수 있어 응용 분야가 포괄적인 그래프 모델이라 할 수 있습니다.
무방향 그래프에서 임의의 두 노드 사이에 경로가 항상 존재하는 그래프입니다.
무방향 그래프에서 임의의 두 노드 사이에 경로가 존재하지 않을 수 있는 그래프입니다.
그래프 내의 모든 노드가 1:1 간선으로 연결된 경우, 즉 연결 가능한 최대 간선 수를 가진 그래프
원래의 그래프에서 일부의 노드나 일부의 간선을 제외하여 만든 그래프를 부분 그래프라고 한다.
두 노드 사이에 여러 개의 간선이 있을 수 있는 그래프입니다.
정점과 간선을 가진 그래프를 컴퓨터가 이해할 수 있는 형태로 표현해야 합니다. 그래프를 컴퓨터가 이해할 수 있도록 표현하는 대표적인 방법에는 인접 리스트(Adjacency List)와 인접 행렬(Adjacency Matrix)이 있습니다.
도시들이 있는데 그 사이에 길이 거의 없다고 생각하면 됩니다. 각 도시를 만드는 데는 많은 공간이 필요하지만, 도시 사이에는 길이 거의 없기 때문에 여행하기도 어렵고, 도시를 만드는 데 사용한 공간이 아까울 수 있습니다. 마찬가지로, 그래프에서 노드(도시)는 많지만 간선(길)이 적으면, 많은 메모리를 사용하지만 그만큼 효율적으로 사용되지 않습니다.
도시는 많지만, 도로는 몇 개 없다면? 그런 정보를 모두 기록하는 것은 공간 낭비입니다. 인접 리스트는 실제 연결된 도로만 기록하기 때문에 이런 경우에는 훨씬 효율적으로 정보를 저장할 수 있습니다.
만약 도시와 도로가 거의 비슷한 수로 많다면, 인접 리스트는 오히려 더 많은 정보를 저장해야 할 수도 있습니다.
각 도시에 연결된 도로 정보뿐만 아니라 그 도로를 통해 어디로 갈 수 있는지도 저장해야 하기 때문입니다.
따라서 이런 경우에는 인접 리스트가 메모리를 더 많이 사용할 수도 있습니다.
class UndirectedGraphAdjacencyMatrix:
def __init__(self, vertices):
# 그래프 클래스를 초기화하는 생성자 함수
self.vertices = vertices # 그래프의 정점 수
self.adjacency_matrix = [[0] * vertices for _ in range(vertices)]
# 인접 행렬을 초기화하고, 모든 원소를 0으로 설정
def add_edge(self, u, v):
# 두 정점 u와 v 사이에 간선을 추가하는 함수
self.adjacency_matrix[u][v] = 1 # 정점 u와 v 사이의 연결을 나타내는 값을 1로 설정
self.adjacency_matrix[v][u] = 1 # 무방향 그래프이므로 반대 방향도 설정
def __str__(self):
# 그래프를 문자열로 표현하기 위한 함수
return '\n'.join([' '.join(map(str, row)) for row in self.adjacency_matrix])
# 인접 행렬을 문자열로 변환하여 반환
# 그래프 생성
vertices = 4
graph = UndirectedGraphAdjacencyMatrix(vertices)
# 4개의 정점을 가지는 무방향 그래프 생성
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 3)
# 간선을 추가하여 그래프를 구성
# 그래프 출력
print("무방향 그래프 인접 행렬:")
print(graph)
# 무방향 그래프를 인접 행렬로 표현한 결과를 출력
출력 결과
무방향 그래프 인접 행렬:
0 1 1 0
1 0 1 0
1 1 0 1
0 0 1 0
class UndirectedGraphAdjacencyList:
def __init__(self, vertices):
# 그래프 클래스를 초기화하는 생성자 함수
self.vertices = vertices # 그래프의 정점 수
self.adjacency_list = [[] for _ in range(vertices)]
# 인접 리스트를 초기화하고, 빈 리스트로 각 정점에 대한 연결 정보를 저장
def add_edge(self, u, v):
# 두 정점 u와 v 사이에 간선을 추가하는 함수
self.adjacency_list[u].append(v) # 정점 u의 연결 리스트에 정점 v를 추가
self.adjacency_list[v].append(u) # 무방향 그래프이므로 정점 v의 연결 리스트에 정점 u를 추가
def __str__(self):
# 그래프를 문자열로 표현하기 위한 함수
result = ""
for vertex, neighbors in enumerate(self.adjacency_list):
result += f"{vertex}: "
result += " ".join(map(str, neighbors))
result += "\n"
return result
# 각 정점과 해당 정점에 인접한 정점들을 문자열로 변환하여 반환
# 그래프 생성
vertices = 4
graph = UndirectedGraphAdjacencyList(vertices)
# 4개의 정점을 가지는 무방향 그래프 생성
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 3)
# 간선을 추가하여 그래프를 구성
# 그래프 출력
print("무방향 그래프 인접 리스트:")
print(graph)
# 무방향 그래프를 인접 리스트로 표현한 결과를 출력
출력 결과
무방향 그래프 인접 리스트:
0: 1 2
1: 0 2
2: 0 1 3
3: 2
class DirectedGraphAdjacencyList:
def __init__(self, vertices):
# 그래프 클래스를 초기화하는 생성자 함수
self.vertices = vertices # 그래프의 정점 수
self.adjacency_list = [[] for _ in range(vertices)]
# 인접 리스트를 초기화하고, 빈 리스트로 각 정점에 대한 연결 정보를 저장
def add_edge(self, u, v):
# 정점 u에서 v로의 방향 간선을 추가하는 함수
self.adjacency_list[u].append(v) # 정점 u의 연결 리스트에 정점 v를 추가
def __str__(self):
# 그래프를 문자열로 표현하기 위한 함수
result = ""
for vertex, neighbors in enumerate(self.adjacency_list):
result += f"{vertex} -> "
result += " ".join(map(str, neighbors))
result += "\n"
return result
# 각 정점과 해당 정점에서 나가는 간선의 목적지를 문자열로 변환하여 반환
# 그래프 생성
vertices = 4
graph = DirectedGraphAdjacencyList(vertices)
# 4개의 정점을 가지는 방향 그래프 생성
graph.add_edge(0, 1)
graph.add_edge(1, 2)
graph.add_edge(2, 3)
graph.add_edge(3, 0)
# 방향 간선을 추가하여 그래프를 구성
# 그래프 출력
print("방향 그래프 인접 리스트:")
print(graph)
# 방향 그래프를 인접 리스트로 표현한 결과를 출력
출력 결과
방향 그래프 인접 리스트:
0 -> 1
1 -> 2
2 -> 3
3 -> 0
class WeightedDirectedGraphAdjacencyList:
def __init__(self, vertices):
# 그래프 클래스를 초기화하는 생성자 함수
self.vertices = vertices # 그래프의 정점 수
self.adjacency_list = [[] for _ in range(vertices)]
# 인접 리스트를 초기화하고, 빈 리스트로 각 정점에 대한 연결 정보를 저장
def add_edge(self, u, v, weight):
# 정점 u에서 v로의 방향 간선과 가중치를 추가하는 함수
self.adjacency_list[u].append((v, weight))
# 정점 u의 연결 리스트에 정점 v와 가중치를 추가
def __str__(self):
# 그래프를 문자열로 표현하기 위한 함수
result = ""
for vertex, neighbors in enumerate(self.adjacency_list):
result += f"{vertex} -> "
result += " ".join([f"({neighbor[0]}, {neighbor[1]})" for neighbor in neighbors])
result += "\n"
return result
# 각 정점과 해당 정점에서 나가는 간선의 목적지와 가중치를 문자열로 변환하여 반환
# 그래프 생성
vertices = 4
graph = WeightedDirectedGraphAdjacencyList(vertices)
# 4개의 정점을 가지는 방향 가중치 그래프 생성
graph.add_edge(0, 1, 2)
graph.add_edge(1, 2, 3)
graph.add_edge(2, 3, 1)
graph.add_edge(3, 0, 4)
# 방향 간선과 가중치를 추가하여 그래프를 구성
# 그래프 출력
print("방향 가중치 그래프 인접 리스트:")
print(graph)
# 방향 가중치 그래프를 인접 리스트로 표현한 결과를 출력
출력 결과
방향 가중치 그래프 인접 리스트:
0 -> (1, 2)
1 -> (2, 3)
2 -> (3, 1)
3 -> (0, 4)