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:
Yudong Jin
2026-03-30 07:30:15 +08:00
committed by GitHub
parent fe6443235b
commit d7b2277d2b
1444 changed files with 83312 additions and 8363 deletions
@@ -1,34 +1,34 @@
# 二分木の配列表現
連結リスト表現では、二分木の格納単位はノード`TreeNode`であり、ノードはポインタによって接続されます。連結リスト表現での二分木の基本操作については前の節で紹介しました。
連結リスト表現では、二分木の記憶単位はノード `TreeNode` であり、ノード同士はポインタによって接続されます。前節では、連結リスト表現における二分木の各種基本操作紹介しました。
では、配列を使って二分木を表現することはできるでしょうか?答えはイエスです。
では、配列二分木を表現できるでしょうか?答えはもちろん可能です。
## 完全二分木表現
## 充足二分木表現する
まず簡単なケースから分析してみましょう。完全二分木が与えられたとき、レベル順探索の順序に従ってすべてのノードを配列格納、各ノードは一意配列インデックスに対応します。
まず簡単な例を考えます。与えられた 1 本の充足二分木について、すべてのノードをレベル順走査の順に配列格納すると、各ノードは一意配列インデックスに対応します。
レベル順探索の特性に基づいて、親ノードのインデックスとその子ノードの間の「マッピング公式」を導き出すことができます**ノードのインデックスが$i$の場合、その左子のインデックスは$2i + 1$、右子のインデックスは$2i + 2$です**。下図は、さまざまなノードインデックス間のマッピング関係を示しています。
レベル順走査の性質に基づくと、親ノードのインデックスと子ノードのインデックスの間にある「対応式」を導けます**あるノードのインデックスが $i$ なら、その左子ノードのインデックスは $2i + 1$ 、右子ノードのインデックスは $2i + 2$ です**。以下の図は、各ノードインデックス間の対応関係を示しています。
![完全二分木の配列表現](array_representation_of_tree.assets/array_representation_binary_tree.png)
![充足二分木の配列表現](array_representation_of_tree.assets/array_representation_binary_tree.png)
**マッピング公式は、連結リストノード参照(ポインタ)と同様の役割を果たします**。配列内の任意のノードが与えられたとき、マッピング公式を使用してその左(右)子ノードにアクセスできます。
**対応式は、連結リストにおけるノード参照(ポインタ)と同役割を果たします**与えられた配列内の任意のノードについて、この対応式を使えばその左(右)子ノードにアクセスできます。
## 任意の二分木表現
## 任意の二分木表現する
完全二分木は特なケースです。二分木の中間レベルには多くの`None`が存在することがよくあります。レベル順探索のシーケンスにはこれらの`None`が含まれないため、このシーケンスだけに依存して`None`の数分布を推することはできません。**つまり、複数の二分木構造が同じレベル順探索シーケンスと一致する可能性があります**。
充足二分木は特なケースであり、一般の二分木では中間層に多数の `None` が存在することがよくあります。レベル順走査の列にはこれらの `None` が含まれないため、その列だけから `None` の数分布位置を推することはできません。**つまり、このレベル順走査列に一致する二分木構造は複数存在し得ます**。
下図に示すように、完全でない二分木が与えられた場合、上記の配列表現方法は失敗します
次の図のように、非充足二分木が与えられると、上記の配列表現はすでに成り立ちません
![レベル順探索シーケンスが複数の二分木の可能性に対応](array_representation_of_tree.assets/array_representation_without_empty.png)
![レベル順走査列に対応する複数の二分木の可能性](array_representation_of_tree.assets/array_representation_without_empty.png)
この問題を解決するために、**レベル順探索シーケンスですべての`None`を明示的に書き出すことを検討できます**。下図に示すように、この処理後、レベル順探索シーケンスは二分木を一意に表現できます。サンプルコードは以下のりです:
この問題を解決するために、**レベル順走査列にすべての `None` を明示的に書き込む**ことを考えられます。次の図のように、このように処理すればレベル順走査列で二分木を一意に表現できます。コードは以下のとおりです:
=== "Python"
```python title=""
# 二分木の配列表現
# Noneを使用して空のスロットを表現
# 空き位置を表すために None を使
tree = [1, 2, 3, 4, None, 6, 7, 8, 9, None, None, 12, None, None, 15]
```
@@ -36,7 +36,7 @@
```cpp title=""
/* 二分木の配列表現 */
// 最大整数値INT_MAXを使用して空のスロットをマーク
// int の最大値 INT_MAX を使って空き位置を示す
vector<int> tree = {1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15};
```
@@ -44,7 +44,7 @@
```java title=""
/* 二分木の配列表現 */
// Integerラッパークラスを使用してnullで空のスロットをマーク
// intラッパークラス Integer を使えば、null で空き位置を示せる
Integer[] tree = { 1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15 };
```
@@ -52,7 +52,7 @@
```csharp title=""
/* 二分木の配列表現 */
// nullable int (int?)を使用してnullで空のスロットをマーク
// nullable な int? 型を使えば、null で空き位置を示せる
int?[] tree = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
@@ -60,7 +60,7 @@
```go title=""
/* 二分木の配列表現 */
// anyスライスを使用してnilで空のスロットをマーク
// any 型のスライスを使えば、nil で空き位置を示せる
tree := []any{1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15}
```
@@ -68,7 +68,7 @@
```swift title=""
/* 二分木の配列表現 */
// optional Int (Int?)を使用してnilで空のスロットをマーク
// nullable な Int? 型を使えば、nil で空き位置を示せる
let tree: [Int?] = [1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15]
```
@@ -76,7 +76,7 @@
```javascript title=""
/* 二分木の配列表現 */
// nullを使用して空のスロットを表
// null を使って空き位置を表
let tree = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
@@ -84,7 +84,7 @@
```typescript title=""
/* 二分木の配列表現 */
// nullを使用して空のスロットを表
// null を使って空き位置を表
let tree: (number | null)[] = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
@@ -92,7 +92,7 @@
```dart title=""
/* 二分木の配列表現 */
// nullable int (int?)を使用してnullで空のスロットをマーク
// nullable な int? 型を使えば、null で空き位置を示せる
List<int?> tree = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
@@ -100,7 +100,7 @@
```rust title=""
/* 二分木の配列表現 */
// Noneを使用して空のスロットをマーク
// None を使って空き位置を示す
let tree = [Some(1), Some(2), Some(3), Some(4), None, Some(6), Some(7), Some(8), Some(9), None, None, Some(12), None, None, Some(15)];
```
@@ -108,7 +108,7 @@
```c title=""
/* 二分木の配列表現 */
// 最大int値を使用して空のスロットをマーク、したがってノード値はINT_MAXであってはならない
// int の最大値で空き位置を示すため、ノード値は INT_MAX であってはならない
int tree[] = {1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15};
```
@@ -116,43 +116,45 @@
```kotlin title=""
/* 二分木の配列表現 */
// nullを使用して空のスロットを表
val tree = mutableListOf( 1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15 )
// null を使って空き位置を表
val tree = arrayOf( 1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15 )
```
=== "Ruby"
```ruby title=""
### 二分木の配列表現 ###
# nil を使って空き位置を表す
tree = [1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15]
```
![任意の種類の二分木の配列表現](array_representation_of_tree.assets/array_representation_with_empty.png)
![任意の二分木の配列表現](array_representation_of_tree.assets/array_representation_with_empty.png)
注目すべきは、**完二分木は配列表現に非常に適している**ということです。完二分木の定義を思い出すと、`None`は最下位レベルでのみ、かつ右側に向かって現れます。**つまり、すべての`None`値は確実にレベル順探索シーケンスの最後に現れます**。
補足すると、**完二分木は配列による表現に非常に適しています**。完二分木の定義を振り返ると、`None` は最下層の右側にしか現れないため、**すべての `None` は必ずレベル順走査列の末尾に現れます**。
これは、配列を使用して完備二分木を表現する際、すべての`None`の格納を省略できることを意味し、非常に便利です。図に例を示します。
つまり、完全二分木を配列で表す場合は、すべての `None` の格納を省略できるため、非常に便利です。次の図に例を示します。
![完二分木の配列表現](array_representation_of_tree.assets/array_representation_complete_binary_tree.png)
![完二分木の配列表現](array_representation_of_tree.assets/array_representation_complete_binary_tree.png)
以下のコードは、配列表現に基づく二分木を実装し、次の操作を含みます
以下のコードは、配列ベースで表現した二分木を実装しており、次の操作を含みます
- ノードが与えられたとき、その値、左(右)子ノード、および親ノードを取得する。
- 前順、中順、後順、およびレベル順探索シーケンスを取得する。
- あるノードが与えられたとき、その値、左(右)子ノード、親ノードを取得する。
- 前順走査、中順走査、後順走査、レベル順走査の列を取得する。
```src
[file]{array_binary_tree}-[class]{array_binary_tree}-[func]{}
```
## 利点と制
## 利点と制
二分木の配列表現には以下の利点があります
二分木の配列表現には主に次の利点があります
- 配列は連続したメモリ空間に格納されるため、キャッシュフレンドリーで、より高速なアクセスと探索が可能です
- ポインタを格納する必要がないため、スペースを節約できます
- ノードへのランダムアクセスが可能で
- 配列は連続したメモリ空間に格納されるため、キャッシュ効率が高く、アクセスと走査が速い
- ポインタを格納する必要がなく、比較的省スペースである
- ノードへのランダムアクセスが可能である
しかし、配列表現にはいくつかの制もあります
ただし、配列表現にはいくつかの制もあります
- 配列格納には連続したメモリ空間が必要なため、大量のデータを持つ木の格納には適していません
- ノードの追加削除は配列の挿入削除操作が必要で、効率が低くなります
- 二分木に多くの`None`値がある場合、配列に含まれるノードデータの割合が低くなり、空間利用率低下します。
- 配列による格納には連続したメモリ空間が必要なため、データ量が大きすぎる木の格納には向かない
- ノードの追加削除は配列の挿入削除操作で実現する必要があり、効率は低い
- 二分木に大量の `None` が存在すると、配列に占める実ノードデータの比率が低くなり、空間利用率低下す