As árvores de pesquisa binária equilibrada são essenciais para garantir pesquisas O (log n) (ou operações similares). Em um ambiente dinâmico em que muitas chaves são inseridas e / ou excluídas aleatoriamente, as árvores podem degenerar em listas vinculadas que são horríveis para pesquisas. Portanto, existem vários tipos de árvores binárias de auto-equilíbrio que neutralizam esse efeito (como árvores AVL ou árvores espalhadas ). Essas árvores são baseadas em diferentes tipos de rotações que reequilibram a árvore.
Rotações
Neste desafio, veremos apenas as rotações à direita, uma rotação (a rotação à esquerda seria simétrica) é assim:
5 3
/ \ / \
3 6 => 1 5
/ \ / \
1 4 4 6
Se alguma das folhas 1
, 4
ou 6
tivesse subárvores esquerda ou direita, uma rotação simplesmente as manteria lá. Se essa é uma subárvore de uma árvore maior, simplesmente "a cortamos" no nó 5
e "reconectamos" a árvore girada (agora nó 3
) a esse nó.
Desafio
Dada uma árvore de pesquisa binária 1 e uma chave, gire com o botão direito a árvore nesse nó, conforme descrito acima. A chave fornecida no exemplo acima seria 5
.
Regras e E / S
- você pode usar qualquer tipo de chave desde que haja uma bijeção entre as chaves de sua escolha e as dos casos de teste
- você pode escolher qualquer representação para árvores binárias, desde que não haja ambiguidade (por exemplo,
[3,[]]
seja ambígua, a menos que seja especificado de outra forma) e seja natural para o seu idioma de escolha - como a entrada sempre será uma árvore de pesquisa binária, não há chaves duplicadas
- você pode assumir que a chave está contida na árvore
- você pode assumir que o nó que contém a chave tem um filho esquerdo
- você não pode assumir uma subárvore direita sob a chave fornecida
- você não pode assumir que a árvore está desequilibrada antes da rotação
- você não pode assumir que a árvore está equilibrada após a rotação
- você pode usar qualquer método de E / S padrão
- seu envio pode ser uma função retornando a árvore ou um programa completo imprimindo a solução
Casos de teste
Estes exemplos representam uma árvore da seguinte maneira
- se é uma folha:
[]
- se é uma árvore com chave
x
e as duas subárvores são folhas:[x]
- se é uma árvore com chave
x
e subárvoresleft
right
:[x,left,right]
O primeiro exemplo é o fornecido na seção Rotações . Se por algum motivo você precisa de uma representação gráfica deles, aqui 2 que você vá.
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: significando que, para qualquer nó, todas as chaves na subárvore esquerda serão menores que essa chave e todas as chaves na subárvore direita serão maiores que ele
2: para evitar o rot-link, eu os incorporei como um comentário
data B=B[B]Int
pouparia mais alguns bytes.