# Обход двоичного дерева С физической точки зрения дерево является структурой данных, основанной на связном списке, поэтому его обход осуществляется последовательным доступом к узлам через указатели. Однако, будучи нелинейной структурой данных, обход дерева сложнее, чем обход связного списка, и требует использования алгоритмов поиска. Наиболее распространенные методы обхода двоичного дерева включают обход по уровням, прямой, симметричный и обратный обходы. ## Обход по уровням Обход по уровням осуществляется сверху вниз, выполняется последовательный обход двоичного дерева с посещением узлов на каждом уровне слева направо, как показано на рис. 7.9. Обход по уровням по своей сути является обходом в ширину, также называемым поиском в ширину, который характеризуется постепенно расширяющимся кольцом от центра к периферии. ![Обход двоичного дерева по уровням](../assets/media/image228.jpeg) ### Код реализации Обход в ширину обычно реализуется с использованием очереди. Очередь следует принципу «первый вошел -- первый вышел», а обход в ширину -- принципу «поэтапное продвижение», что делает их концептуально схожими. Ниже приведен код реализации. ```src [file]{binary_tree_bfs}-[class]{}-[func]{level_order} ``` ### Анализ сложности **Временная сложность** *O*(*n*): каждый узел посещается один раз, что занимает *O*(*n*) времени выполнения, где *n* -- количество узлов. **Пространственная сложность** *O*(*n*): в худшем случае, т. е. в полном двоичном дереве, до достижения самого нижнего уровня в очереди может находиться одновременно (*n* + 1)/2 узлов, что занимает *O*(*n*) пространства. ## Прямой, симметричный и обратный обходы Прямой, симметричный и обратный обходы относятся к обходам в глубину, также называемым поиск в глубину, который характеризуется подходом «сначала до конца, затем возврат и продолжение». На рис. 7.10 демонстрируется принцип работы обхода в глубину для двоичного дерева. **Обход в глубину можно представить как обход двоичного дерева по периметру**, при этом на каждом узле встречаются три позиции, соответствующие прямому, симметричному и обратному обходам. ![Прямой, симметричный и обратный обходы двоичного дерева](../assets/media/image237.jpeg) ### Код реализации Поиск в глубину обычно реализуется на основе рекурсии. ```src [file]{binary_tree_dfs}-[class]{}-[func]{post_order} ``` На рис. 7.11 демонстрируется рекурсивный процесс прямого обхода двоичного дерева, который можно разделить на два противоположных этапа: рекурсия и возврат. 1. Рекурсия означает начало нового метода, в процессе которого программа посещает следующий узел. 2. Возврат означает возвращение функции, что указывает на завершение посещения текущего узла. === "<1>" ![Рекурсивный процесс прямого обхода](../assets/media/image246.jpeg) === "<2>" ![preorder_step2](../assets/media/image249.jpeg) === "<3>" ![preorder_step3](../assets/media/image251.jpeg) === "<4>" ![preorder_step4](../assets/media/image253.jpeg) === "<5>" ![preorder_step5](../assets/media/image256.jpeg) === "<6>" ![preorder_step6](../assets/media/image259.jpeg) === "<7>" ![preorder_step7](../assets/media/image261.jpeg) === "<8>" ![preorder_step8](../assets/media/image263.jpeg) === "<9>" ![preorder_step9](../assets/media/image266.jpeg) === "<10>" ![preorder_step10](../assets/media/image269.jpeg) === "<11>" ![preorder_step11](../assets/media/image271.jpeg) ### Анализ сложности **Временная сложность** *O*(*n*): все узлы посещаются один раз, что занимает *O*(*n*) времени. **Пространственная сложность** *O*(*n*): в худшем случае, когда дерево вырождается в список, глубина рекурсии достигает *n*, система занимает *O*(*n*) пространства стека.