Files
hello-algo/ru/docs/chapter_tree/summary.md
Yudong Jin 772183705e Add ru version (#1865)
* Add Russian docs site baseline

* Add Russian localized codebase

* Polish Russian code wording

* Update ru code translation.

* Update code translation and chapter covers.

* Fix pythontutor extraction.

* Add README and landing page.

* placeholder of profiles

* Use figures of English version

* Remove chapter paperbook
2026-03-28 04:24:07 +08:00

10 KiB
Raw Blame History

Краткие итоги

Основные моменты

  • Двоичное дерево - это нелинейная структура данных, отражающая логику "разделения надвое". Каждый узел двоичного дерева содержит значение и два указателя, которые соответственно ведут к левому и правому дочерним узлам.
  • Для любого узла двоичного дерева дерево, образованное его левым (правым) дочерним узлом и всеми нижележащими узлами, называется левым (правым) поддеревом этого узла.
  • К связанным с двоичным деревом терминам относятся корневой узел, листовой узел, уровень, степень, ребро, высота, глубина и так далее.
  • Инициализация двоичного дерева, вставка узлов и удаление узлов похожи по способу реализации на операции со связным списком.
  • К распространенным видам двоичного дерева относятся идеальное двоичное дерево, полное двоичное дерево, строгое двоичное дерево и сбалансированное двоичное дерево. Идеальное двоичное дерево - наиболее желательное состояние, а связный список - худший случай после вырождения.
  • Двоичное дерево можно представить массивом: значения узлов и пустые позиции располагаются в порядке обхода по уровням, а связи между родителем и детьми реализуются через отображение индексов.
  • Обход двоичного дерева по уровням является методом поиска в ширину; он отражает идею "расширяться слой за слоем наружу" и обычно реализуется через очередь.
  • Прямой, симметричный и обратный обходы относятся к поиску в глубину; они отражают идею "сначала дойти до конца, затем откатиться и продолжить" и обычно реализуются рекурсивно.
  • Двоичное дерево поиска - это эффективная структура данных для поиска элементов; его поиск, вставка и удаление имеют временную сложность O(\log n) . Когда двоичное дерево поиска вырождается в связный список, все эти сложности деградируют до O(n) .
  • AVL-дерево, также называемое сбалансированным двоичным деревом поиска, с помощью вращений гарантирует, что после постоянных вставок и удалений узлов дерево остается сбалансированным.
  • Вращения AVL-дерева включают правое вращение, левое вращение, сначала правое затем левое и сначала левое затем правое. После вставки или удаления узла AVL-дерево выполняет вращения снизу вверх, чтобы снова восстановить баланс.

Q & A

Q: Для двоичного дерева, состоящего из одного узла, высота дерева и глубина корня обе равны 0 ?

Да, потому что высота и глубина обычно определяются как "число пройденных ребер".

Q: Вставка и удаление в двоичном дереве обычно выполняются в составе набора операций. Что именно означает этот "набор операций"? Можно ли понимать это как освобождение ресурсов у дочерних узлов ресурса?

Возьмем в качестве примера двоичное дерево поиска: операция удаления узла делится на три случая, и каждый из этих случаев требует нескольких последовательных шагов работы с узлами.

Q: Почему у DFS для двоичного дерева есть три порядка: прямой, симметричный и обратный? Для чего они нужны?

Подобно прямому и обратному обходу массива, прямой, симметричный и обратный обходы - это три способа обхода двоичного дерева, с помощью которых можно получить результаты в определенном порядке. Например, в двоичном дереве поиска, где соблюдается отношение значение левого дочернего узла < значение корня < значение правого дочернего узла , если обходить дерево с приоритетом "лево \rightarrow корень \rightarrow право", то получится упорядоченная последовательность узлов.

Q: Правое вращение работает с отношениями между node , child и grand_child . А связь между node и его исходным родителем разве не нужно поддерживать? После правого вращения она ведь не оборвется?

На это нужно смотреть с точки зрения рекурсии. В правое вращение right_rotate(root) передается корень поддерева, а затем через return child возвращается корень этого поддерева уже после вращения. Соединение между новым корнем поддерева и его родителем восстанавливается после возврата функции и не входит в обязанности самой операции правого вращения.

Q: В C++ функции делятся на private и public . Какая логика стоит за этим? Почему height() и updateHeight() помещают в разные области видимости?

Главный критерий - область использования метода. Если метод нужен только внутри класса, его следует проектировать как private . Например, самостоятельный вызов updateHeight() пользователем не имеет смысла: это лишь один из шагов внутри вставки или удаления. А height() используется для чтения высоты узла, подобно vector.size() , поэтому его разумно делать public .

Q: Как построить двоичное дерево поиска из набора входных данных? Важен ли выбор корневого узла?

Да, важен. Способ построения дерева уже показан в методе build_tree() в коде двоичного дерева поиска. Что касается выбора корня, обычно входные данные сортируют, берут средний элемент как корень, а затем рекурсивно строят левое и правое поддеревья. Это позволяет в наибольшей степени сохранить баланс дерева.

Q: Нужно ли в Java всегда использовать equals() для сравнения строк?

В Java для базовых типов == используется, чтобы сравнивать, равны ли значения двух переменных. Для ссылочных типов логика у этих двух способов уже разная.

  • == : сравнивает, ссылаются ли две переменные на один и тот же объект, то есть совпадает ли их адрес в памяти.
  • equals(): сравнивает, равны ли значения двух объектов.

Поэтому если нужно сравнить значения, то следует использовать equals() . Но строки, инициализированные как String a = "hi"; String b = "hi"; , хранятся в строковом пуле констант и указывают на один и тот же объект, поэтому в таком случае a == b тоже может дать истинный результат при сравнении содержимого.

Q: До достижения самого нижнего уровня при обходе в ширину число узлов в очереди равно 2^h ?

Да. Например, для полного двоичного дерева высоты h = 2 общее число узлов равно n = 7 , а число узлов на нижнем уровне равно 4 = 2^h = (n + 1) / 2 .