mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-13 15:56:05 +00:00
Re-translate the Japanese version (#1871)
* Retranslate Japanese docs with GPT-5.4 * Retranslate Japanese code with GPT-5.4
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
# グラフの基本操作
|
||||
|
||||
グラフの基本操作は「辺」に対する操作と「頂点」に対する操作に分けることができます。「隣接行列」と「隣接リスト」の2つの表現方法の下では、実装が異なります。
|
||||
グラフの基本操作は、「辺」に対する操作と「頂点」に対する操作に分けられます。「隣接行列」と「隣接リスト」の 2 つの表現方法では、実装方法が異なります。
|
||||
|
||||
## 隣接行列に基づく実装
|
||||
|
||||
$n$個の頂点を持つ無向グラフが与えられた場合、さまざまな操作は下図のように実装されます。
|
||||
頂点数が $n$ の無向グラフを与えると、各種操作の実装方法は次図のとおりです。
|
||||
|
||||
- **辺の追加または削除**:隣接行列内の指定された辺を直接変更し、$O(1)$時間を使用します。無向グラフであるため、両方向の辺を同時に更新する必要があります。
|
||||
- **頂点の追加**:隣接行列の末尾に行と列を追加し、すべて$0$で埋めます。$O(n)$時間を使用します。
|
||||
- **頂点の削除**:隣接行列内の行と列を削除します。最悪の場合は最初の行と列が削除されるときで、$(n-1)^2$個の要素を「上と左に移動」する必要があり、$O(n^2)$時間を使用します。
|
||||
- **初期化**:$n$個の頂点を渡し、長さ$n$の頂点リスト`vertices`を初期化し、$O(n)$時間を使用します。$n \times n$サイズの隣接行列`adjMat`を初期化し、$O(n^2)$時間を使用します。
|
||||
- **辺の追加または削除**:隣接行列で指定した辺を直接変更すればよく、$O(1)$ 時間です。無向グラフであるため、2 方向の辺を同時に更新する必要があります。
|
||||
- **頂点の追加**:隣接行列の末尾に 1 行 1 列を追加し、すべてを $0$ で埋めればよく、$O(n)$ 時間です。
|
||||
- **頂点の削除**:隣接行列から 1 行 1 列を削除します。先頭行と先頭列を削除する場合が最悪で、$(n-1)^2$ 個の要素を「左上へ移動」させる必要があるため、$O(n^2)$ 時間です。
|
||||
- **初期化**:$n$ 個の頂点を受け取り、長さ $n$ の頂点リスト `vertices` を初期化するのに $O(n)$ 時間、サイズ $n \times n$ の隣接行列 `adjMat` を初期化するのに $O(n^2)$ 時間かかります。
|
||||
|
||||
=== "隣接行列の初期化"
|
||||

|
||||

|
||||
|
||||
=== "辺の追加"
|
||||

|
||||
@@ -26,7 +26,7 @@ $n$個の頂点を持つ無向グラフが与えられた場合、さまざま
|
||||
=== "頂点の削除"
|
||||

|
||||
|
||||
以下は隣接行列を使用して表現されたグラフの実装コードです:
|
||||
以下は、隣接行列でグラフを表した実装コードです:
|
||||
|
||||
```src
|
||||
[file]{graph_adjacency_matrix}-[class]{graph_adj_mat}-[func]{}
|
||||
@@ -34,16 +34,16 @@ $n$個の頂点を持つ無向グラフが与えられた場合、さまざま
|
||||
|
||||
## 隣接リストに基づく実装
|
||||
|
||||
総計$n$個の頂点と$m$個の辺を持つ無向グラフが与えられた場合、さまざまな操作は下図のように実装できます。
|
||||
無向グラフの頂点総数を $n$、辺総数を $m$ とすると、各種操作は次図の方法で実装できます。
|
||||
|
||||
- **辺の追加**:対応する頂点の連結リストの末尾に辺を追加するだけで、$O(1)$時間を使用します。無向グラフであるため、両方向に同時に辺を追加する必要があります。
|
||||
- **辺の削除**:対応する頂点の連結リスト内で指定された辺を見つけて削除し、$O(m)$時間を使用します。無向グラフでは、両方向の辺を同時に削除する必要があります。
|
||||
- **頂点の追加**:隣接リストに連結リストを追加し、新しい頂点をリストのヘッドノードにし、$O(1)$時間を使用します。
|
||||
- **頂点の削除**:隣接リスト全体を走査し、指定された頂点を含むすべての辺を削除する必要があり、$O(n + m)$時間を使用します。
|
||||
- **初期化**:隣接リストに$n$個の頂点と$2m$個の辺を作成し、$O(n + m)$時間を使用します。
|
||||
- **辺の追加**:頂点に対応する連結リストの末尾に辺を追加すればよく、$O(1)$ 時間です。無向グラフなので、2 方向の辺を同時に追加する必要があります。
|
||||
- **辺の削除**:頂点に対応する連結リストから指定した辺を探して削除するため、$O(m)$ 時間です。無向グラフでは、2 方向の辺を同時に削除する必要があります。
|
||||
- **頂点の追加**:隣接リストに 1 つの連結リストを追加し、新しい頂点をその連結リストの先頭ノードとするため、$O(1)$ 時間です。
|
||||
- **頂点の削除**:隣接リスト全体を走査し、指定した頂点を含むすべての辺を削除する必要があるため、$O(n + m)$ 時間です。
|
||||
- **初期化**:隣接リストに $n$ 個の頂点と $2m$ 本の辺を作成するため、$O(n + m)$ 時間です。
|
||||
|
||||
=== "隣接リストの初期化"
|
||||

|
||||

|
||||
|
||||
=== "辺の追加"
|
||||

|
||||
@@ -57,12 +57,12 @@ $n$個の頂点を持つ無向グラフが与えられた場合、さまざま
|
||||
=== "頂点の削除"
|
||||

|
||||
|
||||
以下は隣接リストのコード実装です。上図と比較して、実際のコードには以下の違いがあります。
|
||||
以下は隣接リストのコード実装です。上図と比べると、実際のコードには次の違いがあります。
|
||||
|
||||
- 頂点の追加と削除の便宜、およびコードの簡素化のため、連結リストの代わりにリスト(動的配列)を使用します。
|
||||
- ハッシュテーブルを使用して隣接リストを格納し、`key`が頂点インスタンス、`value`がその頂点の隣接頂点のリスト(連結リスト)です。
|
||||
- 頂点の追加と削除を容易にし、コードを簡潔にするため、連結リストの代わりにリスト(動的配列)を使用しています。
|
||||
- ハッシュテーブルを用いて隣接リストを格納しており、`key` は頂点インスタンス、`value` はその頂点に隣接する頂点のリスト(連結リスト)です。
|
||||
|
||||
さらに、隣接リストで頂点を表現するために`Vertex`クラスを使用します。その理由は:隣接行列のようにリストインデックスを使用して異なる頂点を区別する場合、インデックス$i$の頂点を削除したい場合、隣接リスト全体を走査し、$i$より大きいすべてのインデックスを1つずつ減少させる必要があり、これは非常に非効率的です。しかし、各頂点が一意の`Vertex`インスタンスである場合、頂点を削除しても他の頂点に変更を加える必要がありません。
|
||||
また、隣接リストでは頂点を表すために `Vertex` クラスを使用しています。その理由は、もし隣接行列と同様にリストのインデックスで異なる頂点を区別すると、インデックス $i$ の頂点を削除する場合、隣接リスト全体を走査して、$i$ より大きいすべてのインデックスを $1$ 減らす必要があり、効率が非常に低いためです。これに対して、各頂点が一意な `Vertex` インスタンスであれば、ある頂点を削除しても他の頂点を変更する必要はありません。
|
||||
|
||||
```src
|
||||
[file]{graph_adjacency_list}-[class]{graph_adj_list}-[func]{}
|
||||
@@ -70,17 +70,17 @@ $n$個の頂点を持つ無向グラフが与えられた場合、さまざま
|
||||
|
||||
## 効率の比較
|
||||
|
||||
グラフに$n$個の頂点と$m$個の辺があると仮定すると、下表は隣接行列と隣接リストの時間効率と空間効率を比較しています。
|
||||
グラフに $n$ 個の頂点と $m$ 本の辺があるとすると、次の表は隣接行列と隣接リストの時間効率および空間効率を比較したものです。なお、隣接リスト(連結リスト)は本記事の実装に対応し、隣接リスト(ハッシュテーブル)はすべての連結リストをハッシュテーブルに置き換えた実装を指します。
|
||||
|
||||
<p align="center"> 表 <id> 隣接行列と隣接リストの比較 </p>
|
||||
|
||||
| | 隣接行列 | 隣接リスト(連結リスト) | 隣接リスト(ハッシュテーブル) |
|
||||
| ---------------- | -------------- | ----------------------- | ----------------------------- |
|
||||
| 隣接性の判定 | $O(1)$ | $O(m)$ | $O(1)$ |
|
||||
| 辺の追加 | $O(1)$ | $O(1)$ | $O(1)$ |
|
||||
| 辺の削除 | $O(1)$ | $O(m)$ | $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)$ |
|
||||
| | 隣接行列 | 隣接リスト(連結リスト) | 隣接リスト(ハッシュテーブル) |
|
||||
| ------------ | -------- | -------------- | ---------------- |
|
||||
| 隣接判定 | $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 回の配列アクセスまたは代入だけです。総合的に見ると、隣接行列は「空間を時間と引き換えにする」原則を体現し、隣接リストは「時間を空間と引き換えにする」原則を体現しています。
|
||||
|
||||
Reference in New Issue
Block a user