mirror of
https://github.com/krahets/hello-algo.git
synced 2026-11-02 03:05:24 +08:00
* 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
84 lines
6.7 KiB
Markdown
84 lines
6.7 KiB
Markdown
# グラフ
|
||
|
||
<u>グラフ(graph)</u>は、<u>頂点(vertex)</u>と<u>辺(edge)</u>からなる非線形データ構造です。グラフ $G$ は、頂点の集合 $V$ と辺の集合 $E$ をまとめたものとして抽象的に表せます。次の例は、5 個の頂点と 7 本の辺を持つグラフです。
|
||
|
||
$$
|
||
\begin{aligned}
|
||
V & = \{ 1, 2, 3, 4, 5 \} \newline
|
||
E & = \{ (1,2), (1,3), (1,5), (2,3), (2,4), (2,5), (4,5) \} \newline
|
||
G & = \{ V, E \} \newline
|
||
\end{aligned}
|
||
$$
|
||
|
||
頂点をノード、辺をノード同士をつなぐ参照(ポインタ)と考えると、グラフは連結リストを拡張したデータ構造として捉えられます。下図のように、**線形の関係(連結リスト)や分割統治の関係(木)よりも、ネットワークの関係(グラフ)は自由度が高く**、その分複雑になります。
|
||
|
||

|
||
|
||
## グラフの主な種類と用語
|
||
|
||
辺に向きがあるかどうかによって、下図のように<u>無向グラフ(undirected graph)</u>と<u>有向グラフ(directed graph)</u>に分けられます。
|
||
|
||
- 無向グラフの辺は、2 頂点間の「双方向」のつながりを表します。WeChat や QQ の「友達関係」がその例です。
|
||
- 有向グラフの辺には向きがあります。つまり、$A \rightarrow B$ と $A \leftarrow B$ の二つの向きの辺は互いに独立しています。Weibo や Douyin の「フォローする」「フォローされる」という関係がその例です。
|
||
|
||

|
||
|
||
すべての頂点がつながっているかどうかによって、下図のように<u>連結グラフ(connected graph)</u>と<u>非連結グラフ(disconnected graph)</u>に分けられます。
|
||
|
||
- 連結グラフでは、ある頂点から出発して、ほかのどの頂点にも到達できます。
|
||
- 非連結グラフでは、ある頂点から出発したとき、到達できない頂点が少なくとも一つあります。
|
||
|
||

|
||
|
||
辺に「重み」という変数を加えると、下図の<u>重み付きグラフ(weighted graph)</u>になります。たとえば『王者荣耀』などのモバイルゲームでは、一緒に遊んだ時間からプレイヤー間の「親密度」を計算します。この親密度のネットワークは、重み付きグラフで表せます。
|
||
|
||

|
||
|
||
グラフでは、次の用語をよく使います。
|
||
|
||
- <u>隣接(adjacency)</u>:2 頂点の間に辺があるとき、これらの頂点は「隣接している」といいます。上図では、頂点 1 に隣接するのは頂点 2、3、5 です。
|
||
- <u>経路(path)</u>:頂点 A から頂点 B までに通る辺の列を、A から B への「経路」といいます。上図の辺の列 1-5-2-4 は、頂点 1 から頂点 4 への経路の一つです。
|
||
- <u>次数(degree)</u>:ある頂点が持つ辺の本数です。有向グラフでは、<u>入次数(in-degree)</u>はその頂点に入る辺の本数、<u>出次数(out-degree)</u>はその頂点から出る辺の本数を表します。
|
||
|
||
## グラフの表現
|
||
|
||
グラフの代表的な表現方法には、「隣接行列」と「隣接リスト」があります。以下では無向グラフを例に説明します。
|
||
|
||
### 隣接行列
|
||
|
||
グラフの頂点数を $n$ とします。<u>隣接行列(adjacency matrix)</u>は、$n \times n$ の行列でグラフを表します。各行(列)が一つの頂点に対応し、行列の要素が辺を表します。2 頂点間に辺があるかどうかを $1$ または $0$ で示します。
|
||
|
||
下図のように、隣接行列を $M$、頂点のリストを $V$ とすると、行列の要素 $M[i, j] = 1$ は頂点 $V[i]$ から頂点 $V[j]$ への辺があることを表し、$M[i, j] = 0$ は辺がないことを表します。
|
||
|
||

|
||
|
||
隣接行列には、次の特徴があります。
|
||
|
||
- 単純グラフでは頂点を自分自身につなげられないため、隣接行列の主対角線上の要素は意味を持ちません。
|
||
- 無向グラフでは両方向の辺が同じものを表すため、隣接行列は主対角線について対称です。
|
||
- 隣接行列の要素 $1$ と $0$ を重みに置き換えると、重み付きグラフを表せます。
|
||
|
||
隣接行列でグラフを表すと、行列の要素に直接アクセスして辺を取得できるため、辺の追加・削除・検索・更新は効率が高く、時間計算量はいずれも $O(1)$ です。ただし、行列の空間計算量は $O(n^2)$ で、メモリを多く使います。
|
||
|
||
### 隣接リスト
|
||
|
||
<u>隣接リスト(adjacency list)</u>は、$n$ 個の連結リストでグラフを表し、連結リストのノードが頂点を表します。$i$ 番目の連結リストは頂点 $i$ に対応し、その頂点に隣接するすべての頂点(その頂点につながる頂点)を格納します。下図に、隣接リストで格納したグラフの例を示します。
|
||
|
||

|
||
|
||
隣接リストは実際に存在する辺だけを保存します。通常、辺の総数は $n^2$ よりはるかに少ないため、空間を節約できます。ただし、辺を探すには連結リストを走査する必要があり、時間効率は隣接行列より低くなります。
|
||
|
||
上図を見ると、**隣接リストの構造はハッシュテーブルの「チェイン法」によく似ているため、同じような方法で効率を改善できます**。たとえば、連結リストが長い場合は AVL 木や赤黒木に変換し、時間計算量を $O(n)$ から $O(\log n)$ に改善できます。ハッシュテーブルに変換すれば、時間計算量を $O(1)$ にできます。
|
||
|
||
## グラフの主な用途
|
||
|
||
下表のように、多くの現実のシステムをグラフでモデル化でき、それらに関する問題をグラフ上の計算問題に帰着できます。
|
||
|
||
<p align="center"> 表 <id> 日常生活に見られるグラフ </p>
|
||
|
||
| | 頂点 | 辺 | グラフ上の計算問題 |
|
||
| -------- | ---- | -------------------- | ------------ |
|
||
| ソーシャルネットワーク | ユーザー | 友達関係 | 友達候補の推薦 |
|
||
| 地下鉄の路線 | 駅 | 駅同士の接続 | 最短経路の推薦 |
|
||
| 太陽系 | 天体 | 天体間の万有引力 | 惑星の軌道計算 |
|