Files
hello-algo/ja/docs/chapter_graph/graph_operations.md
T
Yudong Jin 7257641e0e Retranslate the complete Japanese online edition from Chinese (#2008)
* Retranslate the complete Japanese online edition from Chinese

* Fit Japanese homepage labels and localize heading permalinks

* Point Japanese contribution instructions to the Japanese preview

* Replace locale conditionals with multilingual UI tables
2026-10-30 02:12:26 +08:00

6.1 KiB
Raw Blame History

グラフの基本操作

グラフの基本操作には、「辺」に対する操作と「頂点」に対する操作があります。「隣接行列」と「隣接リスト」では、実装方法が異なります。

隣接行列による実装

頂点数 n の無向グラフに対する各種操作は、下図のように実装できます。

  • 辺の追加・削除:隣接行列の指定した辺を直接変更するだけなので、O(1) 時間です。無向グラフのため、両方向の辺を同時に更新する必要があります。
  • 頂点の追加:隣接行列の末尾に行と列を一つずつ追加し、すべて 0 で埋めます。O(n) 時間かかります。
  • 頂点の削除:隣接行列から行と列を一つずつ削除します。最悪の場合は先頭の行と列を削除するときで、(n-1)^2 個の要素を「左上に移動」するため、O(n^2) 時間かかります。
  • 初期化:n 個の頂点を受け取り、長さ n の頂点リスト vertices を O(n) 時間で初期化します。n \times n の隣接行列 adjMat の初期化には O(n^2) 時間かかります。

=== "<1>" 隣接行列の初期化、辺の追加・削除、頂点の追加・削除

=== "<2>" 隣接行列で辺を追加

=== "<3>" 隣接行列で辺を削除

=== "<4>" 隣接行列で頂点を追加

=== "<5>" 隣接行列で頂点を削除

隣接行列によるグラフの実装を次に示します。

[file]{graph_adjacency_matrix}-[class]{graph_adj_mat}-[func]{}

隣接リストによる実装

無向グラフの頂点数を $n$、辺の総数を m とすると、下図の方法で各種操作を実装できます。

  • 辺の追加:頂点に対応する連結リストの末尾に辺を追加するだけなので、O(1) 時間です。無向グラフのため、両方向の辺を同時に追加する必要があります。
  • 辺の削除:頂点に対応する連結リストで指定した辺を探して削除するため、O(m) 時間かかります。無向グラフでは、両方向の辺を同時に削除する必要があります。
  • 頂点の追加:隣接リストに連結リストを一つ追加し、新しい頂点をその先頭ノードにします。O(1) 時間です。
  • 頂点の削除:隣接リスト全体を走査し、指定した頂点を含むすべての辺を削除するため、O(n + m) 時間かかります。
  • 初期化:隣接リストに n 個の頂点と 2m 本の辺を作るため、O(n + m) 時間かかります。

=== "<1>" 隣接リストの初期化、辺の追加・削除、頂点の追加・削除

=== "<2>" 隣接リストで辺を追加

=== "<3>" 隣接リストで辺を削除

=== "<4>" 隣接リストで頂点を追加

=== "<5>" 隣接リストで頂点を削除

隣接リストの実装を次に示します。実際のコードは、上図と次の点が異なります。

  • 頂点の追加と削除をしやすくし、コードを簡潔にするため、連結リストの代わりにリスト(動的配列)を使います。
  • 隣接リストをハッシュテーブルに格納します。key は頂点のインスタンス、value はその頂点に隣接する頂点のリスト(連結リスト)です。

また、隣接リストでは Vertex クラスで頂点を表します。隣接行列と同じようにリストのインデックスで頂点を区別すると、インデックス i の頂点を削除する際に、隣接リスト全体を走査し、i より大きいインデックスをすべて 1 ずつ減らす必要があり、非効率だからです。各頂点を固有の Vertex インスタンスにすれば、ある頂点を削除しても、ほかの頂点を変更する必要がありません。

[file]{graph_adjacency_list}-[class]{graph_adj_list}-[func]{}

効率の比較

グラフに n 個の頂点と m 本の辺があるとします。下表で、隣接行列と隣接リストの時間効率と空間効率を比較します。隣接リスト(連結リスト)は本節の実装に対応し、隣接リスト(ハッシュテーブル)は、すべての連結リストをハッシュテーブルに置き換えた実装を指します。

表   隣接行列と隣接リストの比較

隣接行列 隣接リスト(連結リスト) 隣接リスト(ハッシュテーブル)
隣接しているかの判定 O(1) O(n) O(1)
辺の追加 O(1) O(1) O(1)
辺の削除 O(1) O(n) O(1)
頂点の追加 O(n) O(1) O(1)
頂点の削除 O(n^2) O(n + m) O(n)
メモリ使用量 O(n^2) O(n + m) O(n + m)

上表だけを見ると、隣接リスト(ハッシュテーブル)が時間効率・空間効率ともに最も優れているように思えます。しかし実際には、隣接行列なら配列へのアクセスまたは代入が 1 回で済むため、辺の操作はより高速です。全体として、隣接行列は「空間を使って時間を節約する」考え方を、隣接リストは「時間を使って空間を節約する」考え方を表しています。