Сбалансированные двоичные деревья поиска необходимы для обеспечения O (log n) поиска (или аналогичных операций). В динамической среде, где множество ключей вставляются и / или удаляются случайным образом, деревья могут вырождаться в связанные списки, которые ужасны для поиска. Таким образом, существуют различные виды самобалансирующихся двоичных деревьев, которые противодействуют этому эффекту (например, деревья AVL или деревья расширения ). Эти деревья основаны на различных видах поворотов, которые перебалансируют дерево.
Повороты
В этой задаче мы рассмотрим только одиночные правые повороты, такой поворот (левый поворот будет симметричным) выглядит следующим образом:
5 3
/ \ / \
3 6 => 1 5
/ \ / \
1 4 4 6
Если какой-либо из листьев 1
, 4
или 6
имеет левое или правое поддеревья, вращение будет просто держать их там. Если это поддерево большего дерева, мы бы просто «обрезали его» в узле 5
и «заново прикрепили» повернутое дерево (теперь узел 3
) к этому узлу.
Вызов
При заданном бинарном дереве поиска 1 и ключе поверните дерево вправо на этом узле, как описано выше. Ключ, предоставленный в приведенном выше примере, будет 5
.
Правила и ввод / вывод
- Вы можете использовать любой тип для ключей, если существует разделение между ключами по вашему выбору и ключами тестовых случаев.
- Вы можете выбрать любое представление для бинарных деревьев, если нет двусмысленности (например,
[3,[]]
двусмысленно, если не указано иное), и это естественно для вашего языка по вашему выбору - поскольку вход всегда будет бинарным деревом поиска, дублирующихся ключей нет
- вы можете предположить, что ключ содержится в дереве
- вы можете предположить, что узел, содержащий ключ, имеет левого потомка
- Вы не можете принять правильное поддерево под предоставленным ключом
- Вы не можете предполагать, что дерево не сбалансировано перед вращением
- вы не можете предполагать, что дерево сбалансировано после поворота
- Вы можете использовать любой метод ввода / вывода по умолчанию
- ваша заявка может быть функцией, возвращающей дерево или полной программой печати решения
Контрольные примеры
Эти примеры представляют дерево следующим образом
- если это лист:
[]
- если это дерево с ключом
x
и оба поддерева являются листьями:[x]
- если это дерево с ключом
x
и поддеревьямиleft
right
:[x,left,right]
Первый пример приведен в разделе « Повороты» . Если по какой - то причине вам нужно графическое представление о них, здесь 2 вы идете.
5 [5,[3,[1],[4]],[6]] -> [3,[1],[5,[4],[6]]]
5 [5,[3,[1],[4]],[]] -> [3,[1],[5,[4],[]]]
5 [5,[3,[],[4]],[6]] -> [3,[],[5,[4],[6]]]
5 [5,[3,[1],[]],[]] -> [3,[1],[5]]
4 [8,[4,[2,[1],[3]],[6,[5],[7]]],[12,[10,[9],[11]],[14,[13],[15]]]] -> [8,[2,[1],[4,[3],[6,[5],[7]]]],[12,[10,[9],[11]],[14,[13],[15]]]]
8 [10,[8,[6,[4,[2,[],[3]],[5]],[7]],[9]],[11]] -> [10,[6,[4,[2,[],[3]],[5]],[8,[7],[9]]],[11]]
10 [10,[8,[6,[4,[2,[],[3]],[5]],[7]],[9]],[11]] -> [8,[6,[4,[2,[],[3]],[5]],[7]],[10,[9],[11]]]
9 [6,[3,[2],[5]],[9,[8],[12,[11],[15,[14],[]]]]] -> [6,[3,[2],[5]],[8,[],[9,[],[12,[11],[15,[14],[]]]]]]
7 [7,[5,[3,[1],[4]],[6]],[8]] -> [5,[3,[1],[4]],[7,[6],[8]]]
15 [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]] -> [17,[9,[5,[2,[0],[4]],[8]],[13,[11,[10],[12]],[15,[14],[16]]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]
21 [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]] -> [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[19,[18],[21,[20],[24,[22],[25]]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]
1: означает, что для любого узла все ключи в левом поддереве будут меньше, чем этот ключ, а все ключи в правом поддереве больше его
2: чтобы не допустить гниения ссылок, я вставил их как комментарий
data B=B[B]Int
позволит сохранить еще несколько байтов.