グラフは、ノード(頂点)とそれらを結ぶエッジ(辺)から構成されるデータ構造です。Pythonを使ってグラフを表現する際には、主に2つの方法があります: 隣接リストと隣接行列です。それぞれの表現方法には利点と欠点がありますので、ここではそれらを詳しく見ていきます。
隣接リストは、各ノードに対して、そのノードから出るエッジのリストを保持するデータ構造です。一般的には、Pythonのリストや辞書を使用して実装します。
以下のコードは、隣接リストを使用して無向グラフを表現する例です。
class Graph:
def __init__(self):
self.adjacency_list = {}
def add_edge(self, u, v):
if u not in self.adjacency_list:
self.adjacency_list[u] = []
if v not in self.adjacency_list:
self.adjacency_list[v] = []
self.adjacency_list[u].append(v)
self.adjacency_list[v].append(u)
def display(self):
for node, edges in self.adjacency_list.items():
print(f"{node}: {', '.join(map(str, edges))}")
# グラフのインスタンスを作成
graph = Graph()
# エッジを追加
graph.add_edge(1, 2)
graph.add_edge(1, 3)
graph.add_edge(2, 4)
graph.add_edge(3, 4)
# グラフを表示
graph.display()
__init__
メソッド: 空の隣接リストを初期化します。これは辞書として実装されます。add_edge
メソッド: 無向エッジを追加するメソッドです。ノードが存在しない場合は新たにリストを初期化し、エッジを追加します。display
メソッド: グラフの隣接リストを表示します。隣接行列は、ノードの数に応じた2次元配列(リストのリスト)を使用して、各ノード間の接続を表します。行列の要素は、エッジが存在する場合は1(またはエッジの重み)、存在しない場合は0となります。
以下のコードは、隣接行列を使用して無向グラフを表現する例です。
class Graph:
def __init__(self, num_vertices):
self.num_vertices = num_vertices
self.adjacency_matrix = [[0] * num_vertices for _ in range(num_vertices)]
def add_edge(self, u, v):
self.adjacency_matrix[u][v] = 1
self.adjacency_matrix[v][u] = 1
def display(self):
for row in self.adjacency_matrix:
print(' '.join(map(str, row)))
# グラフのインスタンスを作成(4つの頂点)
graph = Graph(4)
# エッジを追加
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 3)
graph.add_edge(2, 3)
# グラフを表示
graph.display()
__init__
メソッド: ノード数を受け取り、対応するサイズの隣接行列を初期化します。add_edge
メソッド: 無向エッジを追加するメソッドです。行列の対応する要素を1に設定します。display
メソッド: 隣接行列を表示します。メモリ使用量:
エッジの追加/削除の効率:
探索の効率:
特徴 | 隣接リスト | 隣接行列 |
---|---|---|
メモリ効率 | エッジ数が少ない場合に有利(疎グラフ) | エッジ数が多い場合に有利(密グラフ) |
エッジの存在確認 | 遅い(リスト全体を探索する必要がある) | 高速(( O(1) )) |
隣接ノードの取得 | 高速(リストをそのまま返せば良い) | 遅い(行をすべて探索する必要がある) |
実装の容易さ | 少し複雑(辞書やリストを組み合わせる必要がある) | 簡単(2次元配列を用いる) |
これらの情報を基に、必要に応じて適切な表現方法を選択してください。どちらの方法も特定の状況で有用ですので、状況に応じて使い分けることが大切です。