Files
hello-algo/ru/docs/chapter_tree/binary_tree_traversal.md
Yudong Jin 22b3b568ef fix Ru translation (#1894)
* docs(ru): replace prose quotes with guillemets

* docs(ru): replace prose semicolons with periods

* docs(ru): align animation title forms

* docs(ru): align figure and table references
2026-04-14 18:10:12 +08:00

90 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Обход двоичного дерева
С точки зрения физической структуры дерево представляет собой разновидность структуры данных на основе связей, поэтому его обход выполняется через последовательный доступ к узлам по указателям. Однако дерево является нелинейной структурой данных, а значит, его обход сложнее, чем обход связного списка, и для него требуется использовать поисковые алгоритмы.
К распространенным способам обхода двоичного дерева относятся обход по уровням, прямой обход, симметричный обход и обратный обход.
## Обход по уровням
Как показано на рисунке ниже, <u>обход по уровням (level-order traversal)</u> проходит двоичное дерево сверху вниз по уровням и на каждом уровне посещает узлы слева направо.
По своей сути обход по уровням относится к <u>обходу в ширину (breadth-first traversal)</u>, также называемому <u>поиском в ширину (breadth-first search, BFS)</u>. Он отражает идею «расширяться от центра к периферии слой за слоем».
![Обход двоичного дерева по уровням](binary_tree_traversal.assets/binary_tree_bfs.png)
### Код реализации
Обход в ширину обычно реализуется с помощью «очереди». Очередь подчиняется правилу «первым пришел - первым вышел», а обход в ширину подчиняется правилу «продвигаться по уровням», поэтому стоящая за ними идея согласована. Код реализации приведен ниже:
```src
[file]{binary_tree_bfs}-[class]{}-[func]{level_order}
```
### Анализ сложности
- **Временная сложность равна $O(n)$** : все узлы посещаются по одному разу, поэтому требуется $O(n)$ времени, где $n$ - число узлов.
- **Пространственная сложность равна $O(n)$** : в худшем случае, то есть для полной двоичной деревообразной структуры, до достижения самого нижнего уровня в очереди одновременно может находиться до $(n + 1) / 2$ узлов, что требует $O(n)$ памяти.
## Прямой, симметричный и обратный обходы
Соответственно, прямой, симметричный и обратный обходы относятся к <u>обходу в глубину (depth-first traversal)</u>, также называемому <u>поиском в глубину (depth-first search, DFS)</u>. Он отражает идею «сначала идти до конца, затем возвращаться и продолжать».
На рисунке ниже показан принцип работы обхода двоичного дерева в глубину. **Обход в глубину можно представить как обход всей двоичной структуры по внешнему контуру** , и у каждого узла встречаются три позиции, соответствующие прямому, симметричному и обратному обходам.
![Прямой, симметричный и обратный обходы двоичного дерева поиска](binary_tree_traversal.assets/binary_tree_dfs.png)
### Код реализации
Поиск в глубину обычно реализуется через рекурсию:
```src
[file]{binary_tree_dfs}-[class]{}-[func]{post_order}
```
!!! tip
Поиск в глубину можно реализовать и итеративно. Заинтересованные читатели могут изучить это самостоятельно.
На рисунке ниже показан рекурсивный процесс прямого обхода двоичного дерева. Его можно разделить на две противоположные части: «вход в рекурсию» и «возврат».
1. «Вход в рекурсию» означает запуск нового вызова функции. В этом процессе программа переходит к следующему узлу.
2. «Возврат» означает завершение вызова функции и возврат назад, то есть текущий узел уже полностью обработан.
=== "<1>"
![Рекурсивный процесс прямого обхода](binary_tree_traversal.assets/preorder_step1.png)
=== "<2>"
![preorder_step2](binary_tree_traversal.assets/preorder_step2.png)
=== "<3>"
![preorder_step3](binary_tree_traversal.assets/preorder_step3.png)
=== "<4>"
![preorder_step4](binary_tree_traversal.assets/preorder_step4.png)
=== "<5>"
![preorder_step5](binary_tree_traversal.assets/preorder_step5.png)
=== "<6>"
![preorder_step6](binary_tree_traversal.assets/preorder_step6.png)
=== "<7>"
![preorder_step7](binary_tree_traversal.assets/preorder_step7.png)
=== "<8>"
![preorder_step8](binary_tree_traversal.assets/preorder_step8.png)
=== "<9>"
![preorder_step9](binary_tree_traversal.assets/preorder_step9.png)
=== "<10>"
![preorder_step10](binary_tree_traversal.assets/preorder_step10.png)
=== "<11>"
![preorder_step11](binary_tree_traversal.assets/preorder_step11.png)
### Анализ сложности
- **Временная сложность равна $O(n)$** : все узлы посещаются по одному разу, поэтому требуется $O(n)$ времени.
- **Пространственная сложность равна $O(n)$** : в худшем случае, когда дерево вырождается в связный список, глубина рекурсии достигает $n$ , и система тратит $O(n)$ памяти на стек вызовов.