mirror of
https://github.com/krahets/hello-algo.git
synced 2026-04-23 18:11:45 +08:00
First version.
This commit is contained in:
88
ru/docs/chapter_tree/binary_tree_traversal.md
Normal file
88
ru/docs/chapter_tree/binary_tree_traversal.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Обход двоичного дерева
|
||||
|
||||
С физической точки зрения дерево является структурой данных, основанной на связном списке, поэтому его обход осуществляется последовательным доступом к узлам через указатели. Однако, будучи нелинейной структурой данных, обход дерева сложнее, чем обход связного списка, и требует использования алгоритмов поиска.
|
||||
|
||||
Наиболее распространенные методы обхода двоичного дерева включают обход по уровням, прямой, симметричный и обратный обходы.
|
||||
|
||||
## Обход по уровням
|
||||
|
||||
Обход по уровням осуществляется сверху вниз, выполняется последовательный обход двоичного дерева с посещением узлов на каждом уровне слева направо, как показано на рис. 7.9.
|
||||
|
||||
Обход по уровням по своей сути является обходом в ширину, также называемым поиском в ширину, который характеризуется постепенно расширяющимся кольцом от центра к периферии.
|
||||
|
||||

|
||||
|
||||
### Код реализации
|
||||
|
||||
Обход в ширину обычно реализуется с использованием очереди. Очередь следует принципу «первый вошел -- первый вышел», а обход в ширину -- принципу «поэтапное продвижение», что делает их концептуально схожими. Ниже приведен код реализации.
|
||||
|
||||
```src
|
||||
[file]{binary_tree_bfs}-[class]{}-[func]{level_order}
|
||||
```
|
||||
|
||||
### Анализ сложности
|
||||
|
||||
**Временная сложность** *O*(*n*): каждый узел посещается один раз, что занимает *O*(*n*) времени выполнения, где *n* -- количество узлов.
|
||||
|
||||
**Пространственная сложность** *O*(*n*): в худшем случае, т. е. в полном двоичном дереве, до достижения самого нижнего уровня в очереди может находиться одновременно (*n* + 1)/2 узлов, что занимает *O*(*n*) пространства.
|
||||
|
||||
## Прямой, симметричный и обратный обходы
|
||||
|
||||
Прямой, симметричный и обратный обходы относятся к обходам в глубину, также называемым поиск в глубину, который характеризуется подходом «сначала до конца, затем возврат и продолжение».
|
||||
|
||||
На рис. 7.10 демонстрируется принцип работы обхода в глубину для двоичного дерева. **Обход в глубину можно представить как обход двоичного дерева по периметру**, при этом на каждом узле встречаются три позиции, соответствующие прямому, симметричному и обратному обходам.
|
||||
|
||||

|
||||
|
||||
### Код реализации
|
||||
|
||||
Поиск в глубину обычно реализуется на основе рекурсии.
|
||||
|
||||
```src
|
||||
[file]{binary_tree_dfs}-[class]{}-[func]{post_order}
|
||||
```
|
||||
|
||||
На рис. 7.11 демонстрируется рекурсивный процесс прямого обхода двоичного дерева, который можно разделить на два противоположных этапа: рекурсия и возврат.
|
||||
|
||||
1. Рекурсия означает начало нового метода, в процессе которого программа посещает следующий узел.
|
||||
|
||||
2. Возврат означает возвращение функции, что указывает на завершение посещения текущего узла.
|
||||
|
||||
=== "<1>"
|
||||

|
||||
|
||||
=== "<2>"
|
||||

|
||||
|
||||
=== "<3>"
|
||||

|
||||
|
||||
=== "<4>"
|
||||

|
||||
|
||||
=== "<5>"
|
||||

|
||||
|
||||
=== "<6>"
|
||||

|
||||
|
||||
=== "<7>"
|
||||

|
||||
|
||||
=== "<8>"
|
||||

|
||||
|
||||
=== "<9>"
|
||||

|
||||
|
||||
=== "<10>"
|
||||

|
||||
|
||||
=== "<11>"
|
||||

|
||||
|
||||
### Анализ сложности
|
||||
|
||||
**Временная сложность** *O*(*n*): все узлы посещаются один раз, что занимает *O*(*n*) времени.
|
||||
|
||||
**Пространственная сложность** *O*(*n*): в худшем случае, когда дерево вырождается в список, глубина рекурсии достигает *n*, система занимает *O*(*n*) пространства стека.
|
||||
Reference in New Issue
Block a user