АВЛ-дерево с O(1) бит в каждом узле
НЕТ ВОЙНЕ |
24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян. Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием. Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей. Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить. Антивоенный комитет России |
Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению. |
meduza.io, Популярная политика, Новая газета, zona.media, Майкл Наки. |
Содержание
АВЛ-дерево с бит в каждом узле
Идея
В обычной реализации АВЛ-дерева в каждом узле мы хранили высоту этого узла. Так как высоты левых и правых поддеревьев в АВЛ-дереве отличаются максимум на
, то мы будем хранить не всю высоту дерева, а некоторое число, которое будет показывать, какое поддерево больше, или равны ли они, назовём фактор баланса. Таким образом в каждом узле будет хранится — если высота правого поддерева выше левого, — если высоты равны, и — если правое поддерево выше левого.Операции
Операция добавления
Пусть нам надо добавить ключ . Будем спускаться по дереву, как при поиске ключа . Если мы стоим в вершине и нам надо идти в поддерево, которого нет, то делаем ключ листом, а вершину его корнем. Пересчитываем баланс данного узла . Если он оказался , то высота поддерева с корнем в этой вершине не изменилась и пересчет балансов останавливается. Дальше начинаем подниматься вверх по дереву, исправляя балансы попутных узлов. Если мы поднялись в вершину из левого поддерева, то баланс увеличивается на единицу, если из правого, то уменьшается на единицу. Если мы пришли в вершину и её баланс стал равным или , то это значит, что высота поддерева изменилась и подъём продолжается. Если баланс вершины , в которую мы собираемся идти из ее левого поддерева, равен , то делается поворот для этой вершины . Аналогично делаем поворот, если баланс вершины , в которую мы идем из ее правого поддерева, равен . Если в результате изменения узла, фактор баланса стал равен нулю, то останавливаемся, иначе продолжаем подъём.
Операция удаления
Если вершина — лист, то просто удалим её, иначе найдём ближайшую по значению вершину , поменяем ее местами с удаляемой вершиной и удалим. От удалённой вершины будем подниматься вверх к корню и пересчитывать фактор баланса вершин. Если мы поднялись в вершину из левого поддерева, то фактор баланса уменьшается на единицу, если из правого, то увеличивается на единицу. Если мы пришли в вершину и её баланс стал равным или , то это значит, что высота поддерева не изменилась и подъём можно остановить. Если баланс вершины стал равным нулю, то высота поддерева уменьшилась и подъём нужно продолжить. Если баланс вершины , в которую мы собираемся идти из ее левого поддерева, равен , то делается поворот для этой вершины . Аналогично делаем поворот, если баланс вершины , в которую мы идем из ее правого поддерева, равен . Если в результате изменения узла, фактор баланса стал равен нулю, то подъём продолжается, иначе останавливается.
Балансировка
Опишем операции балансировки, а именно малый левый поворот, большой левый поворот и случаи их возникновения. Балансировка нам нужна для операций добавления и удаления узла. Для исправления факторов баланса, достаточно знать факторы баланса двух(в случае большого поворота — трех) вершин перед поворотом, и исправить значения этих же вершин после поворота. Обозначим фактор баланса вершины
как . Операции поворота делаются на том шаге, когда мы находимся в правом сыне вершины , если мы производим операцию добавления, и в левом сыне, если мы производим операцию удаления. Вычисления производим заранее, чтобы не допустить значения или в вершине . На каждой иллюстрации изображен один случай высот поддеревьев. Нетрудно убедиться, что в остальных случаях всё тоже будет корректно.
Примеры
Ниже приведены примеры добавления и удаления вершины с подписанными изменениями факторов баланса каждой вершины.