Los árboles de búsqueda binarios balanceados son esenciales para garantizar búsquedas O (log n) (u operaciones similares). En un entorno dinámico donde muchas claves se insertan y / o eliminan al azar, los árboles pueden degenerar en listas vinculadas que son horribles para las búsquedas. Por lo tanto, hay varios tipos de árboles binarios autoequilibrados que contrarrestan este efecto (como los árboles AVL o los árboles de separación ). Estos árboles se basan en diferentes tipos de rotaciones que reequilibran el árbol.
Rotaciones
En este desafío, solo veremos rotaciones derechas individuales, tal rotación (la rotación izquierda sería simétrica) se ve así:
5 3
/ \ / \
3 6 => 1 5
/ \ / \
1 4 4 6
Si alguna de las hojas 1
, 4
o 6
tuviera subárboles a la izquierda o derecha, una rotación simplemente las mantendría allí. Si este es un subárbol de un árbol más grande, simplemente lo "cortaríamos" en el nodo 5
y "volveríamos a unir" el árbol girado (ahora nodo 3
) a ese nodo.
Desafío
Dado un árbol de búsqueda binario 1 y una tecla, gire a la derecha el árbol en ese nodo como se describió anteriormente. La clave proporcionada en el ejemplo anterior sería 5
.
Reglas y E / S
- puede usar cualquier tipo de teclas siempre que haya una biyección entre las teclas de su elección y las de los casos de prueba
- puede elegir cualquier representación para árboles binarios siempre que no haya ambigüedad (por ejemplo,
[3,[]]
es ambigua a menos que se especifique lo contrario) y es natural para su idioma de elección - Como la entrada siempre será un árbol de búsqueda binario, no hay claves duplicadas
- puede suponer que la clave está contenida en el árbol
- puede suponer que el nodo que contiene la clave tiene un hijo izquierdo
- es posible que no asuma un subárbol derecho en la clave proporcionada
- es posible que no se asuma que el árbol está desequilibrado antes de la rotación
- es posible que no se asuma que el árbol está equilibrado después de la rotación
- puede usar cualquier método de E / S predeterminado
- su envío puede ser una función que devuelve el árbol o un programa completo que imprime la solución
Casos de prueba
Estos ejemplos representan un árbol de la siguiente manera
- si es una hoja:
[]
- si es un árbol con clave
x
y ambos subárboles son hojas:[x]
- si es un árbol con clave
x
y subárbolesleft
right
:[x,left,right]
El primer ejemplo es el proporcionado en la sección Rotaciones . Si por alguna razón necesita una representación gráfica de ellos, aquí 2 que vaya.
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: lo que significa que para cualquier nodo todas las claves en el subárbol izquierdo serán más pequeñas que esa clave y todas las claves en el subárbol derecho son mayores que
2: para evitar la rotura de enlaces, los incruste como comentario
data B=B[B]Int
ahorraría algunos bytes más.k<n=B[k!l,r]n
yk>n=B[l,k!r]n
, en uno:,k/=n=B[k!l,k!r]n
y luego sumandok!x=x
para que la coincidencia de patrones sea exhaustiva.Vim , 25 bytes
Toma la entrada en el búfer: clave y árbol separados por espacios. Se espera que el árbol se represente de la siguiente manera:
[]
k
, hijo izquierdo<left>
y niño derecho<right>
:[ k <left><right>]
No son los espacios alrededor de la clave los
k
que son importantes, de modo que la solución funciona para árboles arbitrarios.Pruébalo en línea!
Explicación
Avance
Aquí hay una vista previa del primer caso de prueba, generado con este script por Lynn :
fuente
Wolfram Language (Mathematica) , 30 bytes
Pruébalo en línea!
Un árbol representado de la siguiente manera:
$
(puede reemplazarlo por cualquier valor que no sea una clave)x
y subárbolesleft
right
:x[left,right]
Por ejemplo, el árbol en el primer caso de prueba está representado por
5[3[1[$,$],4[$,$]],6[$,$]]
.Explicación:
fuente
Lisp común, 146 bytes
¡Pruébelo en línea o verifique todos los casos de prueba!
Un árbol se representa de la siguiente manera:
nil
(o equivalente en Common Lisp como la lista vacía()
)(node left-subtree right-subtree)
(por lo que una hojaL
se representa como(L nil nil)
).fuente
JavaScript (Node.js) , 70 bytes
Pruébalo en línea! El enlace incluye casos de prueba. Todos los nodos deben tener entradas izquierda y derecha, pero pueden
[]
indicar que no hay subárbol en ese lado. Como abreviatura, el conjunto de pruebas utilizal(N)
para indicar queN
es una hoja yl(N,L)
para indicar queN
tiene un subárbol izquierdoL
pero no un subárbol derecho tanto en la entrada como en la salida.fuente
Python 2 , 85 bytes
Pruébalo en línea!
Formato de entrada:
[KEY, LEFT_SUBTREE, RIGHT_SUBTREE]
[]
fuente
Jalea , 24 bytes
Pruébalo en línea!
Advertencia: Normalmente, la línea superior no debería existir, y la línea inferior debería tener un
ß
, no unç
. Sin embargo, los trucos de la cadena inteligente yß
no van bien juntos, debido aß
Arity variable. Técnicamente, podría haber omitido la línea superior, pero entonces el resultado habría sido un programa completo, ya que de lo contrario tendría que poder incorporarse como su propia línea dentro de cualquier programa, lo cual no es posible a menos que usted Tienes suerte. Esto significa que, desafortunadamente, la salida habría tenido una representación ambigua, porque, cuando envía un programa completo, lo que realmente se obtiene cuenta, y no cuál es el resultado técnico antes de que se cierre el programa. Entonces, para no hacer un lío con la recursión y la representación de cadena adecuada, he decidido enviar una función de 2 líneas, donde el trabajo de la línea superior es solo llamar a la inferior. ¿La consecuencia? Una gran pérdida de 2 bytes preciosos y valiosos. En defensa de Jelly (y Dennis, así como de todos los demás contribuyentes),fuente