Update ru translation

This commit is contained in:
krahets
2026-01-23 00:59:30 +08:00
parent 8071daddaa
commit 19dd60a6be
4 changed files with 579 additions and 108 deletions
@@ -1,4 +1,4 @@
# Представление двоичного дерева с помощью массивом
# Представление двоичного дерева с помощью массива
При представлении в виде списка единицей хранения двоичного дерева является узел `TreeNode`, а узлы соединяются между собой указателями. В предыдущем разделе были рассмотрены основные операции с двоичным деревом, представленным в виде списка.
@@ -8,61 +8,153 @@
Сначала рассмотрим простой пример. Если дано идеальное двоичное дерево и все его узлы хранятся в массиве в порядке обхода по уровням, то каждому узлу соответствует уникальный индекс массива.
На основе свойств обхода по уровням можно вывести формулу отображения между индексом родительского узла и индексами дочерних узлов: **если индекс узла равен $i$, то индекс его левого дочернего узла равен $2i + 1$, а индекс правого дочернего узла равен $2i + 2$**. На рисунке ниже показаны отношения отображения между индексами различных узлов.
На основе свойств обхода по уровням можно вывести формулу соответствия между индексами родительского и дочерних узлов: **если индекс узла равен $i$, то индекс его левого дочернего узла равен $2i + 1$, а правого -- $2i + 2$**. На рис. 7.12 показаны отношения соответствия между индексами узлов.
<!-- 🔴 俄文版缺失图片 -->
<!-- 中文原文:![完美二叉树的数组表示](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`, поэтому невозможно по этой последовательности определить количество и расположение пустых значений. **Это означает, что существует множество структур двоичных деревьев, соответствующих данной последовательности обхода по уровням**.
<!-- 🔴 俄文版缺失此段落 -->
<!-- 中文原文:如下图所示,给定一棵非完美二叉树,上述数组表示方法已经失效。 -->
Для такого неидеального двоичного дерева вышеописанный метод представления с помощью массива уже не работает, см. рис. 7.13.
<!-- 🔴 俄文版缺失图片 -->
<!-- 中文原文:![层序遍历序列对应多种二叉树可能性](array_representation_of_tree.assets/array_representation_without_empty.png) -->
![Для одной последовательности обхода по уровням существует несколько возможных вариантов двоичного дерева](array_representation_of_tree.assets/array_representation_without_empty.png)
<!-- 🔴 俄文版缺失此段落 -->
<!-- 中文原文:为了解决此问题,**我们可以考虑在层序遍历序列中显式地写出所有 `None`** 。如下图所示,这样处理后,层序遍历序列就可以唯一表示二叉树了。示例代码如下: -->
Для решения этой проблемы **можно явно записать все значения `None` в последовательности обхода по уровням**. После такой обработки последовательность обхода по уровням уже может однозначно представлять двоичное дерево, как показано на рис. 7.14. Ниже приведен пример кода.
<!-- 🔴 俄文版缺失代码示例 -->
<!-- 中文原文:=== "Python" ... [多语言代码示例] -->
=== "Python"
<!-- 🔴 俄文版缺失图片 -->
<!-- 中文原文:![任意类型二叉树的数组表示](array_representation_of_tree.assets/array_representation_with_empty.png) -->
```python title=""
# Представление двоичного дерева с помощью массива
# Использование None для обозначения пустых мест
tree = [1, 2, 3, 4, None, 6, 7, 8, 9, None, None, 12, None, None, 15]
```
<!-- 🔴 俄文版缺失此段落 -->
<!-- 中文原文:值得说明的是,**完全二叉树非常适合使用数组来表示**。回顾完全二叉树的定义,`None` 只出现在最底层且靠右的位置,**因此所有 `None` 一定出现在层序遍历序列的末尾**。 -->
=== "C++"
<!-- 🔴 俄文版缺失此段落 -->
<!-- 中文原文:这意味着使用数组表示完全二叉树时,可以省略存储所有 `None` ,非常方便。下图给出了一个例子。 -->
```cpp title=""
/* Представление двоичного дерева с помощью массива */
// Использование 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};
```
<!-- 🔴 俄文版缺失图片 -->
<!-- 中文原文:![完全二叉树的数组表示](array_representation_of_tree.assets/array_representation_complete_binary_tree.png) -->
=== "Java"
<!-- 🔴 俄文版缺失此段落 -->
<!-- 中文原文:以下代码实现了一棵基于数组表示的二叉树,包括以下几种操作。 -->
```java title=""
/* Представление двоичного дерева с помощью массива */
// Использование обертки Integer для типа int, чтобы можно было использовать null для обозначения пустых мест
Integer[] tree = { 1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15 };
```
<!-- 🔴 俄文版缺失列表 -->
<!-- 中文原文:- 给定某节点,获取它的值、左(右)子节点、父节点。- 获取前序遍历、中序遍历、后序遍历、层序遍历序列。 -->
=== "C#"
<!-- 🔴 俄文版缺失代码引用 -->
<!-- 中文原文:```src [file]{array_binary_tree}-[class]{array_binary_tree}-[func]{} ``` -->
```csharp title=""
/* Представление двоичного дерева с помощью массива */
// Использование nullable типа int?, чтобы можно было использовать null для обозначения пустых мест
int?[] tree = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
=== "Go"
```go title=""
/* Представление двоичного дерева с помощью массива */
// Использование типа any для среза, чтобы можно было использовать nil для обозначения пустых мест
tree := []any{1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15}
```
=== "Swift"
```swift title=""
/* Представление двоичного дерева с помощью массива */
// Использование nullable типа Int?, чтобы можно было использовать nil для обозначения пустых мест
let tree: [Int?] = [1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15]
```
=== "JS"
```javascript title=""
/* Представление двоичного дерева с помощью массива */
// Использование null для обозначения пустых мест
let tree = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
=== "TS"
```typescript title=""
/* Представление двоичного дерева с помощью массива */
// Использование null для обозначения пустых мест
let tree: (number | null)[] = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
=== "Dart"
```dart title=""
/* Представление двоичного дерева с помощью массива */
// Использование nullable типа int?, чтобы можно было использовать null для обозначения пустых мест
List<int?> tree = [1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15];
```
=== "Rust"
```rust title=""
/* Представление двоичного дерева с помощью массива */
// Использование 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)];
```
=== "C"
```c title=""
/* Представление двоичного дерева с помощью массива */
// Использование максимального значения 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};
```
=== "Kotlin"
```kotlin title=""
/* Представление двоичного дерева с помощью массива */
// Использование 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)
Стоит отметить, что **совершенное двоичное дерево очень удобно представлять с помощью массива**. Вспоминая определение совершенного двоичного дерева, `None` появляются только на самом нижнем уровне и в правой части, поэтому **все значения `None` обязательно находятся в конце последовательности обхода по уровням**.
Это означает, что при использовании массива для представления совершенного двоичного дерева можно опустить хранение всех `None`, что очень удобно. На рис. 7.15 приведен пример такого представления.
![Представление совершенного двоичного дерева с помощью массива](array_representation_of_tree.assets/array_representation_complete_binary_tree.png)
В коде ниже реализуется двоичное дерево, основанное на представлении с помощью массива, включая следующие операции.
- Для заданного узла получение его значения, левого и правого дочернего узла, родительского узла.
- Получение последовательностей обхода в прямом, симметричном, обратном порядке и в порядке обхода по уровням.
```src
[file]{array_binary_tree}-[class]{array_binary_tree}-[func]{}
```
## Преимущества и ограничения
<!-- 🔴 俄文版缺失此段落 -->
<!-- 中文原文:二叉树的数组表示主要有以下优点。 -->
Представление двоичного дерева с помощью массива имеет следующие преимущества:
<!-- 🔴 俄文版缺失列表 -->
<!-- 中文原文:- 数组存储在连续的内存空间中,对缓存友好,访问与遍历速度较快。- 不需要存储指针,比较节省空间。- 允许随机访问节点。 -->
- Массив хранится в непрерывной области памяти, что хорошо для кеширования. Скорость доступа и обхода достаточно высока.
- Не требуется хранение указателей, что экономит пространство.
- Позволяет выполнять произвольный доступ к узлам.
<!-- 🔴 俄文版缺失此段落 -->
<!-- 中文原文:然而,数组表示也存在一些局限性。 -->
Однако представление с помощью массива имеет и некоторые ограничения:
<!-- 🔴 俄文版缺失列表 -->
<!-- 中文原文:- 数组存储需要连续内存空间,因此不适合存储数据量过大的树。- 增删节点需要通过数组插入与删除操作实现,效率较低。- 当二叉树中存在大量 `None` 时,数组中包含的节点数据比重较低,空间利用率较低。 -->
- Хранение в массиве требует непрерывной области памяти, поэтому не подходит для хранения деревьев с очень большим объемом данных.
- Добавление и удаление узлов требует выполнения операций вставки и удаления в массиве, которые менее эффективны.
- Когда в двоичном дереве содержится много значений `None`, доля данных узлов в массиве низка, что приводит к низкой эффективности использования пространства.