Cuestión 1. Construcción con rotaciones
Insertamos 10, 20, 30, 40, 50, 25 partiendo del árbol vacío. Notación: cada nodo se anota como clave(FE), con FE = altura(izq) − altura(der) y altura de un subárbol vacío = −1, hoja = 0.
Inserción de 10 → raíz.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 70" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<circle cx="80" cy="35" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="80" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
</svg>
Inserción de 20 → a la derecha de 10.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 150" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="100" y1="55" x2="150" y2="105" stroke="#334155" stroke-width="1.5"/>
<circle cx="100" cy="35" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="100" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(-1)</text>
<circle cx="160" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="160" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(0)</text>
</svg>
FE(10) = −1, equilibrado. Sin rotación.
Inserción de 30 → a la derecha de 20. Antes de rotar:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="100" y1="55" x2="150" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="160" y1="135" x2="210" y2="185" stroke="#334155" stroke-width="1.5"/>
<circle cx="100" cy="35" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="100" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(-2)</text>
<circle cx="160" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="160" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(-1)</text>
<circle cx="220" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="220" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(0)</text>
</svg>
El nodo desequilibrado más bajo es
10 con
FE = −2; el camino de inserción fue derecha-derecha →
caso RR → rotación simple a la izquierda sobre 10. 20 sube a raíz:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280 150" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="140" y1="55" x2="80" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="160" y1="55" x2="220" y2="105" stroke="#334155" stroke-width="1.5"/>
<circle cx="150" cy="35" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="150" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(0)</text>
<circle cx="70" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="230" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="230" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(0)</text>
</svg>
Inserción de 40 → a la derecha de 30.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 340 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="140" y1="55" x2="80" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="160" y1="55" x2="220" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="240" y1="135" x2="290" y2="185" stroke="#334155" stroke-width="1.5"/>
<circle cx="150" cy="35" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="150" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(-1)</text>
<circle cx="70" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="230" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="230" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(-1)</text>
<circle cx="300" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="300" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(0)</text>
</svg>
FE(30) = −1,
FE(20) = −1. Equilibrado, sin rotación.
Inserción de 50 → a la derecha de 40. Antes de rotar:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 310" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="140" y1="55" x2="80" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="160" y1="55" x2="220" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="240" y1="135" x2="290" y2="185" stroke="#334155" stroke-width="1.5"/>
<line x1="310" y1="215" x2="350" y2="265" stroke="#334155" stroke-width="1.5"/>
<circle cx="150" cy="35" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="150" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(-2)</text>
<circle cx="70" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="230" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="230" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(-2)</text>
<circle cx="300" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="300" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(-1)</text>
<circle cx="360" cy="275" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="360" y="275" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
</svg>
El desequilibrado
más bajo es
30 (
FE = −2), camino derecha-derecha →
caso RR → rotación simple a la izquierda sobre 30. 40 sube ocupando el lugar de 30:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="140" y1="55" x2="80" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="160" y1="55" x2="290" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="290" y1="135" x2="240" y2="185" stroke="#334155" stroke-width="1.5"/>
<line x1="310" y1="135" x2="360" y2="185" stroke="#334155" stroke-width="1.5"/>
<circle cx="150" cy="35" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="150" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(-1)</text>
<circle cx="70" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="300" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="300" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(0)</text>
<circle cx="230" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="230" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(0)</text>
<circle cx="370" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="370" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
</svg>
Tras la rotación, 20 queda con
FE = −1: equilibrado. (Regla AVL: en inserción, una sola rotación restablece el equilibrio de todo el árbol).
Inserción de 25 → BST: 25 > 20 → derecha; 25 < 40 → izquierda; 25 < 30 → izquierda de 30. Antes de rotar:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440 310" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="150" y1="55" x2="80" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="170" y1="55" x2="290" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="290" y1="135" x2="240" y2="185" stroke="#334155" stroke-width="1.5"/>
<line x1="310" y1="135" x2="370" y2="185" stroke="#334155" stroke-width="1.5"/>
<line x1="220" y1="215" x2="180" y2="265" stroke="#334155" stroke-width="1.5"/>
<circle cx="160" cy="35" r="22" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
<text x="160" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(-2)</text>
<circle cx="70" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="300" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="300" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(+1)</text>
<circle cx="230" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="230" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(+1)</text>
<circle cx="380" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="380" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
<circle cx="170" cy="275" r="22" fill="#ecfdf5" stroke="#059669" stroke-width="1.5"/>
<text x="170" y="275" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">25(0)</text>
</svg>
Recalculamos FE camino arriba:
FE(30) = +1 y
FE(40) = +1 siguen dentro del invariante, pero
FE(20) = altura(10) − altura(40) = 0 − 2 = −2. El desequilibrado más bajo (y único) es
20. El camino desde 20 hacia la zona de inserción fue
derecha-luego-izquierda (20→40 a la derecha, 40→30 a la izquierda) →
caso RL → rotación doble: primero,
rotación simple a la derecha sobre el hijo derecho (40), en la que 30 sube y 40 baja a su derecha:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 470 310" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="150" y1="55" x2="80" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="170" y1="55" x2="290" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="290" y1="135" x2="180" y2="185" stroke="#334155" stroke-width="1.5"/>
<line x1="310" y1="135" x2="360" y2="185" stroke="#334155" stroke-width="1.5"/>
<line x1="370" y1="215" x2="410" y2="265" stroke="#334155" stroke-width="1.5"/>
<circle cx="160" cy="35" r="22" fill="#fef2f2" stroke="#dc2626" stroke-width="2"/>
<text x="160" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(-2)</text>
<circle cx="70" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="300" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="300" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(-1)</text>
<circle cx="170" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="170" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">25(0)</text>
<circle cx="370" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="370" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(-1)</text>
<circle cx="420" cy="275" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="420" y="275" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
</svg>
Ojo: este es solo el
paso intermedio — 20 sigue con
FE = −2, pero el camino ha quedado derecha-derecha (caso RR). Segunda mitad de la doble rotación:
rotación simple a la izquierda sobre 20. 30 sube a la raíz:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="210" y1="50" x2="130" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="230" y1="50" x2="310" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="110" y1="130" x2="80" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="130" y1="130" x2="160" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="330" y1="130" x2="380" y2="180" stroke="#334155" stroke-width="1.5"/>
<circle cx="220" cy="35" r="22" fill="#ecfdf5" stroke="#059669" stroke-width="1.5"/>
<text x="220" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(0)</text>
<circle cx="120" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="120" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(0)</text>
<circle cx="320" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="320" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(-1)</text>
<circle cx="70" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="170" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="170" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">25(0)</text>
<circle cx="390" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="390" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
</svg>
Comprobación de FE tras la doble rotación:
FE(10) = 0, FE(25) = 0, FE(50) = 0 (hojas)
FE(20) = altura(10) − altura(25) = 0 − 0 = 0
FE(40) = altura(∅) − altura(50) = −1 − 0 = −1
FE(30) = altura(20) − altura(40) = 1 − 1 = 0
Todos los FE ∈ {−1, 0}, árbol AVL válido.
Árbol final con factores de equilibrio:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="210" y1="50" x2="130" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="230" y1="50" x2="310" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="110" y1="130" x2="80" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="130" y1="130" x2="160" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="330" y1="130" x2="380" y2="180" stroke="#334155" stroke-width="1.5"/>
<circle cx="220" cy="35" r="22" fill="#f8fafc" stroke="#2563eb" stroke-width="2"/>
<text x="220" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(0)</text>
<circle cx="120" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="120" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(0)</text>
<circle cx="320" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="320" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(-1)</text>
<circle cx="70" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="170" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="170" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">25(0)</text>
<circle cx="390" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="390" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
</svg>
Altura mínima. El árbol tiene altura h = 2 (contando aristas: por ejemplo 30→40→50). Es la mínima posible para 6 claves: un árbol completo de altura 2 (3 niveles) almacena hasta 2^3 − 1 = 7 ≥ 6 nodos, mientras que uno de altura 1 solo aloja 3. Comprobado: nuestro AVL alcanza la altura mínima.
Como apunte de nivel tribunal: el AVL no garantiza siempre la altura mínima absoluta, sino la cota h ≤ 1,44·log₂(n+2) (árboles de Fibonacci). En este caso concreto el resultado sí coincide con el mínimo teórico y, en general, la altura queda siempre en O(log n).
Cuestión 2. Por qué AVL y no BST
Forma del BST sin equilibrar con 10, 20, 30, 40, 50. Como cada clave es mayor que todas las anteriores, siempre se inserta como hijo derecho del último nodo. El BST degenera en una lista enlazada inclinada a la derecha:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 390" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="80" y1="55" x2="130" y2="105" stroke="#334155" stroke-width="1.5"/>
<line x1="150" y1="135" x2="200" y2="185" stroke="#334155" stroke-width="1.5"/>
<line x1="220" y1="215" x2="270" y2="265" stroke="#334155" stroke-width="1.5"/>
<line x1="290" y1="295" x2="340" y2="345" stroke="#334155" stroke-width="1.5"/>
<circle cx="70" cy="35" r="22" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10</text>
<circle cx="140" cy="115" r="22" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="140" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20</text>
<circle cx="210" cy="195" r="22" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="210" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30</text>
<circle cx="280" cy="275" r="22" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="280" y="275" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40</text>
<circle cx="350" cy="355" r="22" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="350" y="355" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50</text>
</svg>
- Altura:
h = n − 1 = 4 aristas (5 niveles). En general, para n claves ordenadas, h = n − 1.
- Coste de búsqueda: buscar la clave 50 (o una inexistente mayor) recorre los n nodos → O(n). La búsqueda binaria se ha perdido por completo; el BST se comporta como una búsqueda secuencial.
Garantía O(log n) del AVL. El invariante FE ∈ {−1,0,+1} mantiene la altura acotada. Se demuestra con los números de Fibonacci: el AVL con menos nodos para una altura h tiene N(h) = N(h−1) + N(h−2) + 1 nodos (árbol de Fibonacci). De ahí se deduce:
h \le 1{,}4404 \cdot \log_2(n + 2) - 0{,}328 \approx O(\log n)
Como búsqueda, inserción y borrado recorren un único camino raíz→hoja y solo aplican un número constante de rotaciones por nivel afectado, su coste es proporcional a la altura → O(log n) en todos los casos, frente al O(n) del peor caso del BST.
Información extra en cada nodo. Cada nodo AVL debe almacenar, además de clave e hijos, su altura (o, equivalentemente, su factor de equilibrio). Con la altura de los hijos se recalcula en O(1):
\text{altura}(nodo) = 1 + \max\big(\text{altura}(izq),\ \text{altura}(der)\big)
FE(nodo) = \text{altura}(izq) - \text{altura}(der)
Mantener la altura/FE actualizado tras cada inserción o borrado es lo que permite detectar el desequilibrio y decidir la rotación sin recorrer el subárbol completo.
Cuestión 3. Borrado de la clave 30
Partimos del árbol final de la cuestión 1:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="210" y1="50" x2="130" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="230" y1="50" x2="310" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="110" y1="130" x2="80" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="130" y1="130" x2="160" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="330" y1="130" x2="380" y2="180" stroke="#334155" stroke-width="1.5"/>
<circle cx="220" cy="35" r="22" fill="#f8fafc" stroke="#2563eb" stroke-width="2"/>
<text x="220" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">30(0)</text>
<circle cx="120" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="120" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(0)</text>
<circle cx="320" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="320" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(-1)</text>
<circle cx="70" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="170" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="170" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">25(0)</text>
<circle cx="390" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="390" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
</svg>
Paso 1 — Localizar y elegir sustituto. El nodo 30 es ahora la raíz y tiene dos hijos (el subárbol 20-10-25 y la rama 40-50). En un nodo con dos hijos se sustituye por el predecesor in-orden (máximo del subárbol izquierdo, aquí el 25) o el sucesor in-orden (mínimo del subárbol derecho). Tomamos el sucesor in-orden: el mínimo del subárbol derecho de 30 es 40 (40 no tiene hijo izquierdo). Copiamos la clave 40 en la raíz y eliminamos el nodo 40 original, reenganchando su hijo derecho (50) en su lugar.
Subárboles afectados: el subárbol derecho (la rama 40-50). Tras copiar 40 arriba, 50 pasa a colgar directamente de la nueva raíz:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="210" y1="50" x2="130" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="230" y1="50" x2="310" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="110" y1="130" x2="80" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="130" y1="130" x2="160" y2="180" stroke="#334155" stroke-width="1.5"/>
<circle cx="220" cy="35" r="22" fill="#ecfdf5" stroke="#059669" stroke-width="1.5"/>
<text x="220" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(?)</text>
<circle cx="120" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="120" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(0)</text>
<circle cx="320" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="320" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
<circle cx="70" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="170" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="170" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">25(0)</text>
</svg>
Paso 2 — Recalcular alturas y FE subiendo hacia la raíz.
FE(10) = 0, FE(25) = 0, FE(50) = 0 (hojas).
FE(20) = altura(10) − altura(25) = 0 − 0 = 0 → equilibrado.
FE(40) (la nueva raíz) = altura(20) − altura(50) = 1 − 0 = +1 → equilibrado.
Paso 3 — ¿Desequilibrio? No. Todos los FE quedan en {−1, 0, +1}. El borrado no provoca desequilibrio, por lo que no se requiere ninguna rotación en este caso.
Árbol resultante:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<line x1="210" y1="50" x2="130" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="230" y1="50" x2="310" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="110" y1="130" x2="80" y2="180" stroke="#334155" stroke-width="1.5"/>
<line x1="130" y1="130" x2="160" y2="180" stroke="#334155" stroke-width="1.5"/>
<circle cx="220" cy="35" r="22" fill="#f8fafc" stroke="#2563eb" stroke-width="2"/>
<text x="220" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">40(+1)</text>
<circle cx="120" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="120" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">20(0)</text>
<circle cx="320" cy="115" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="320" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">50(0)</text>
<circle cx="70" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="70" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">10(0)</text>
<circle cx="170" cy="195" r="22" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="170" y="195" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">25(0)</text>
</svg>
Nota sobre propagación. A diferencia de la inserción (donde una única rotación restablece todo el árbol), en el borrado una rotación puede reducir la altura del subárbol y desequilibrar a un ancestro, obligando a propagar el reequilibrado hacia la raíz (potencialmente O(log n) rotaciones). En este supuesto concreto no llega a producirse, pero el algoritmo general debe seguir comprobando el FE en cada ancestro hasta la raíz.
Cuestión 4. Esquema de la rotación simple a la derecha
La rotación simple a la derecha se aplica al caso LL (el subárbol izquierdo es el más alto y el desequilibrio viene por la izquierda del hijo izquierdo). El hijo izquierdo h sube a ocupar el lugar del nodo desequilibrado z, que baja a la derecha; el antiguo subárbol derecho de h (T2) se reengancha como subárbol izquierdo de z.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 620 240" font-family="ui-sans-serif, system-ui, Arial, sans-serif">
<!-- Árbol izquierdo: antes -->
<line x1="95" y1="50" x2="65" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="115" y1="50" x2="150" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="55" y1="125" x2="30" y2="175" stroke="#334155" stroke-width="1.5"/>
<line x1="75" y1="125" x2="100" y2="175" stroke="#334155" stroke-width="1.5"/>
<circle cx="105" cy="35" r="18" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="105" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">z</text>
<circle cx="65" cy="115" r="18" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="65" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">h</text>
<rect x="145" y="98" width="36" height="34" rx="4" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="163" y="115" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#0f172a">T3</text>
<rect x="12" y="173" width="36" height="34" rx="4" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="30" y="190" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#0f172a">T1</text>
<rect x="82" y="173" width="36" height="34" rx="4" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="100" y="190" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#0f172a">T2</text>
<!-- Flecha -->
<line x1="240" y1="120" x2="360" y2="120" stroke="#2563eb" stroke-width="2"/>
<polygon points="360,120 348,114 348,126" fill="#2563eb"/>
<text x="300" y="108" text-anchor="middle" font-size="12" fill="#2563eb">rotarDerecha</text>
<!-- Árbol derecho: después -->
<line x1="455" y1="50" x2="425" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="475" y1="50" x2="510" y2="100" stroke="#334155" stroke-width="1.5"/>
<line x1="500" y1="125" x2="475" y2="175" stroke="#334155" stroke-width="1.5"/>
<line x1="520" y1="125" x2="545" y2="175" stroke="#334155" stroke-width="1.5"/>
<circle cx="465" cy="35" r="18" fill="#ecfdf5" stroke="#059669" stroke-width="1.5"/>
<text x="465" y="35" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">h</text>
<rect x="407" y="98" width="36" height="34" rx="4" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="425" y="115" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#0f172a">T1</text>
<circle cx="510" cy="115" r="18" fill="#eff6ff" stroke="#334155" stroke-width="1.5"/>
<text x="510" y="115" text-anchor="middle" dominant-baseline="middle" font-size="13" fill="#0f172a">z</text>
<rect x="457" y="173" width="36" height="34" rx="4" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="475" y="190" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#0f172a">T2</text>
<rect x="527" y="173" width="36" height="34" rx="4" fill="#f8fafc" stroke="#334155" stroke-width="1.5"/>
<text x="545" y="190" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#0f172a">T3</text>
</svg>
Java:
Nodo rotarDerecha(Nodo z) {
Nodo h = z.izq; // hijo izquierdo, será la nueva raíz
Nodo T2 = h.der; // subárbol que cambia de padre
// 1) Reasignación de punteros (orden seguro: primero "girar")
h.der = z; // z pasa a ser hijo derecho de h
z.izq = T2; // T2 pasa a ser hijo izquierdo de z
// 2) Recalcular alturas: PRIMERO el nodo que queda abajo (z),
// LUEGO el que queda arriba (h), porque h depende de z.
z.altura = 1 + Math.max(altura(z.izq), altura(z.der));
h.altura = 1 + Math.max(altura(h.izq), altura(h.der));
// 3) Devolver la nueva raíz del subárbol
return h;
}
int altura(Nodo n) { return (n == null) ? -1 : n.altura; }
Punteros reasignados y orden:
- Guardar
h = z.izq y T2 = h.der antes de modificar nada (si no, se pierden las referencias).
h.der = z (z baja a la derecha de h).
z.izq = T2 (T2 cuelga de z).
- Recalcular alturas de abajo arriba: primero
z (queda como hijo) y después h (queda como nueva raíz y su altura depende de la ya actualizada de z).
- Retornar
h para que el padre re-enlace el subárbol.
El coste es O(1) (número constante de reasignaciones).
Composición de la rotación LR (en una frase): el caso LR se resuelve con dos rotaciones simples encadenadas: primero una rotación a la izquierda sobre el hijo izquierdo del nodo desequilibrado (lo transforma en un caso LL) y, a continuación, una rotación a la derecha sobre el propio nodo desequilibrado. Simétricamente, RL = rotación derecha sobre el hijo derecho + rotación izquierda sobre el nodo.
Cuestión 5. Comparación con tabla hash
| Criterio |
Árbol AVL |
Tabla hash |
| Búsqueda — caso medio |
O(log n) |
O(1) |
| Búsqueda — peor caso |
O(log n) (garantizado por el invariante) |
O(n) (todas las claves colisionan en el mismo cubo) |
| Inserción / borrado |
O(log n) |
O(1) medio / O(n) peor |
| Recorrido ordenado |
O(n) in-orden, sin coste extra |
No soportado; exige extraer todo y ordenar → O(n·log n) |
| Consulta por rango |
O(log n + k) |
Ineficiente: hay que examinar todos los cubos → O(n) |
| Memoria |
Punteros por nodo + altura |
Array + gestión de colisiones |
(a) Complejidad de la búsqueda por clave.
- AVL: O(log n) tanto en caso medio como en el peor caso, porque la altura está acotada logarítmicamente por el invariante de equilibrio.
- Tabla hash: O(1) en el caso medio (con buena función hash y factor de carga controlado), pero O(n) en el peor caso, cuando todas las claves caen en el mismo cubo (colisiones masivas o función hash deficiente).
(b) Operaciones «gratis» del AVL. Al ser un árbol binario de búsqueda ordenado, el AVL ofrece sin coste adicional:
- Recorrido ordenado (in-orden): visita las claves de menor a mayor
id en O(n), directamente.
- Consultas por rango (p. ej. «recursos con id entre 100 y 200»): O(log n + k), localizando el extremo inferior y avanzando in-orden.
- Además: mínimo / máximo (O(log n)) y predecesor / sucesor de una clave.
Una tabla hash no preserva ningún orden entre las claves: el hashing dispersa los id por los cubos sin relación con su valor, de modo que recorrer ordenado o consultar rangos obliga a leer toda la tabla y reordenar.
(c) Factor de carga. El factor de carga es:
\lambda = \frac{n}{m} \qquad (n = \text{núm. de elementos almacenados},\ m = \text{núm. de cubos/buckets})
Mide cómo de «llena» está la tabla. Al crecer λ aumenta la probabilidad de colisión y, por tanto, la longitud media de las listas de desbordamiento (en encadenamiento) o el número de sondeos (en direccionamiento abierto), degradando el O(1) ideal. Para mantener el rendimiento se realiza rehashing (se amplía m y se reubican las claves) cuando λ supera un umbral típico (≈ 0,75 en encadenamiento; menor, ≈ 0,5, en direccionamiento abierto).
Conclusión. Si el requisito principal es listar los recursos ordenados por id (y previsiblemente hacer consultas por rango), la elección correcta es el árbol AVL: ofrece el recorrido ordenado y las consultas por rango de forma nativa y eficiente, con búsqueda/inserción/borrado garantizados en O(log n) incluso en el peor caso. La tabla hash sería preferible solo si la operación dominante fuera el acceso puntual por clave exacta sin necesidad de orden ni rangos, donde su O(1) medio resulta imbatible.