Сбалансированные двоичные деревья поиска необходимы для обеспечения 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
позволит сохранить еще несколько байтов.k<n=B[k!l,r]n
иk>n=B[l,k!r]n
, в один:,k/=n=B[k!l,k!r]n
а затем добавив,k!x=x
чтобы сделать сопоставление с образцом исчерпывающим.Vim , 25 байт
Берет ввод в буфер - разделенный пробелом ключ и дерево. Ожидается, что дерево будет представлено следующим образом:
[]
k
, левой дочерней<left>
и правой дочерней<right>
:[ k <left><right>]
Не пробелы вокруг ключа,
k
которые важны, так что решение работает для произвольных деревьев.Попробуйте онлайн!
объяснение
предварительный просмотр
Вот предварительный просмотр первого контрольного примера, созданного с помощью этого сценария Линн :
источник
Wolfram Language (Mathematica) , 30 байтов
Попробуйте онлайн!
Дерево представлено следующим образом:
$
(вы можете заменить его любым значением, которое не является ключевым)x
и поддеревьямиleft
right
:x[left,right]
Например, дерево в первом тестовом примере представлено как
5[3[1[$,$],4[$,$]],6[$,$]]
.Объяснение:
источник
Common Lisp, 146 байт
Попробуйте онлайн или проверьте все тестовые случаи!
Дерево представляется следующим образом:
nil
(или эквивалентно в Common Lisp как пустой список()
)(node left-subtree right-subtree)
(таким образом, листL
представляется как(L nil nil)
).источник
JavaScript (Node.js) , 70 байт
Попробуйте онлайн! Ссылка включает в себя тестовые случаи. Все узлы должны иметь левые и правые записи, но они могут указывать
[]
на отсутствие поддерева на этой стороне. В качестве аббревиатуры набор тестов используетсяl(N)
для указания того, чтоN
это лист, иl(N,L)
для указания того, что уN
него есть левое поддерево,L
но нет правого поддерева как на входе, так и на выходе.источник
Python 2 , 85 байт
Попробуйте онлайн!
Формат ввода:
[KEY, LEFT_SUBTREE, RIGHT_SUBTREE]
[]
источник
Желе , 24 байта
Попробуйте онлайн!
Предупреждение: как правило, верхняя строка не должна существовать, а нижняя строка должна иметь, а
ß
неç
. Тем не менее, хитрые цепные трюки иß
не подходят друг другу, из-заß
переменная арность. Технически, я все еще мог бы опустить верхнюю строку, но тогда результатом должна была бы быть полная программа, так как в противном случае она должна была бы быть в состоянии включить ее как собственную строку в любую программу, что невозможно, если вы повезло. Это означает, что, к сожалению, выходные данные имели бы неоднозначное представление, потому что, когда вы отправляете полную программу, на самом деле учитывается то, что получено, а не то, что технически является результатом до закрытия программы. Поэтому, чтобы не путать рекурсию и правильное представление строки, я решил представить двухстрочную функцию, в которой задача верхней строки состоит в том, чтобы просто вызвать нижнюю. Следствие? Огромная трата 2 ценных и ценных байтов. В защиту Джелли (и Дениса, как и любого другого участника),источник