Menu
Coddy logo textTech

Árbol AVL

Última actualización

Un árbol AVL es un árbol binario de búsqueda autoequilibrado. Funciona como un BST normal, pero después de cada inserción comprueba el factor de equilibrio de cada ancestro - la diferencia de altura entre sus subárboles izquierdo y derecho - y si algún nodo queda desequilibrado (una diferencia mayor que 1), realiza rotaciones para restaurar el equilibrio. Pulsa reproducir arriba para ver cómo se insertan los valores y el árbol se rota de nuevo a su forma correcta.

Como nunca deja que el árbol se incline más que ligeramente, un árbol AVL garantiza una altura de O(log n), por lo que la búsqueda, inserción y eliminación son siempre O(log n) - incluso para entradas ordenadas que destrozarían un BST normal. El coste son las rotaciones adicionales y el mantenimiento de la altura en cada inserción.

Complejidad temporal y espacial

OperaciónComplejidadNotas
BúsquedaO(log n)La altura es siempre ~1.44 log n
InserciónO(log n)Más O(1) rotaciones
EliminaciónO(log n)Más O(log n) rotaciones
EspacioO(n)Un campo de altura por nodo

Los cuatro casos de rotación

CasoDesequilibrioCorrección
Izquierda-IzquierdaPesado en la izquierda del hijo izquierdoUna rotación a la derecha
Derecha-DerechaPesado en la derecha del hijo derechoUna rotación a la izquierda
Izquierda-DerechaPesado en la derecha del hijo izquierdoRotación a la izquierda y luego a la derecha
Derecha-IzquierdaPesado en la izquierda del hijo derechoRotación a la derecha y luego a la izquierda

Ejemplo resuelto

Insertando [10, 20, 30, 40, 50, 25] un valor a la vez:

PasoEstructuraAcción
Insertar 1010El primer nodo se convierte en la raíz; equilibrado
Insertar 2010(_, 20)Va a la derecha de 10; sigue equilibrado
Insertar 3020(10, 30)Derecha-Derecha en 10, así que una rotación a la izquierda eleva 20 a la raíz
Insertar 4020(10, 30(_, 40))Va a la derecha de 30; todos los factores de equilibrio se mantienen dentro de ±1
Insertar 5020(10, 40(30, 50))Derecha-Derecha en 30, así que una rotación a la izquierda en 30 eleva 40
Insertar 2530(20(10, 25), 40(_, 50))Derecha-Izquierda en 20: rota a la derecha el subárbol de 40 y luego rota a la izquierda 20

Cuándo usar un árbol AVL

Úsalo cuandoEvítalo cuando
Las búsquedas superan con creces a las inserciones y quieres la altura más ajustada posibleLas inserciones y eliminaciones dominan - las rotaciones y el reequilibrio adicionales cuestan más que en un árbol rojo-negro
Necesitas un peor caso garantizado de O(log n), incluso para entradas adversarias u ordenadasUna tabla hash simple bastaría - no necesitas recorrido ordenado ni consultas por rango
Necesitas operaciones ordenadas: recorrido en orden, predecesor/sucesor, consultas por rangoEl conjunto de datos es minúsculo - un BST normal o un array ordenado es más simple y suficientemente rápido
Los datos pueden llegar ya ordenados, lo que convertiría un BST no equilibrado en una lista enlazadaNo puedes permitirte la memoria extra del campo de altura por nodo en un espacio muy ajustado

Código de AVL Tree

Una implementación limpia y ejecutable de AVL Tree en Python, JavaScript, Java, C++, C. Elige un lenguaje, copia el código o ábrelo ya cargado en el Playground de Coddy.

Código de AVL Tree en Python

Python
1class Node:2    def __init__(self, key):3        self.key = key4        self.left = None5        self.right = None6        self.height = 17
8
9def height(node):10    return node.height if node else 011
12
13def update(node):14    node.height = 1 + max(height(node.left), height(node.right))15
16
17def rotate_right(y):18    x = y.left19    y.left = x.right20    x.right = y21    update(y)22    update(x)23    return x24
25
26def rotate_left(x):27    y = x.right28    x.right = y.left29    y.left = x30    update(x)31    update(y)32    return y33
34
35def insert(node, key):36    if node is None:37        return Node(key)38    if key < node.key:39        node.left = insert(node.left, key)40    else:41        node.right = insert(node.right, key)42    update(node)43    balance = height(node.left) - height(node.right)44    # Four imbalance cases: LL, RR, LR, RL45    if balance > 1 and key < node.left.key:46        return rotate_right(node)47    if balance < -1 and key > node.right.key:48        return rotate_left(node)49    if balance > 1:50        node.left = rotate_left(node.left)51        return rotate_right(node)52    if balance < -1:53        node.right = rotate_right(node.right)54        return rotate_left(node)55    return node56
57
58def inorder(node):59    if node is None:60        return []61    return inorder(node.left) + [node.key] + inorder(node.right)62
63
64root = None65for key in [10, 20, 30, 40, 50, 25]:66    root = insert(root, key)67
68print("Inorder:", inorder(root))69print("Root:", root.key, "| tree height:", root.height)
Ejecuta este código en el Playground de Python

Preguntas frecuentes sobre el árbol AVL

¿Qué es un factor de equilibrio en un árbol AVL?
El factor de equilibrio de un nodo es la altura de su subárbol izquierdo menos la altura de su subárbol derecho. Un árbol AVL mantiene el factor de equilibrio de cada nodo en -1, 0 o +1; si una inserción lo saca de ese rango, una rotación restaura el equilibrio.
¿Cuál es la diferencia entre un árbol AVL y un árbol rojo-negro?
Ambos son BST autoequilibrados con operaciones O(log n). Los árboles AVL están más estrictamente equilibrados, por lo que las búsquedas son ligeramente más rápidas, pero pueden hacer más rotaciones en inserción/eliminación. Los árboles rojo-negro están más laxamente equilibrados, favoreciendo menos rotaciones - por eso muchas bibliotecas estándar los usan para mapas y conjuntos.
¿Por qué usar un árbol AVL en lugar de un árbol binario de búsqueda normal?
Un BST normal puede degradarse a operaciones O(n) si los valores llegan en orden, formando una cadena sesgada. Un árbol AVL rota para mantenerse equilibrado, garantizando una altura y operaciones O(log n) sin importar el orden de inserción.
¿Es un árbol AVL mejor que un árbol rojo-negro para un índice de base de datos?
Depende de la carga de trabajo. Los árboles AVL están más rígidamente equilibrados, así que ganan cuando las lecturas dominan y quieres las rutas de búsqueda más cortas posibles. Pero la mayoría de las bases de datos y bibliotecas de lenguajes eligen árboles rojo-negro (o árboles B) porque reequilibran con menos rotaciones en cargas con muchas escrituras, lo que importa más cuando las inserciones y eliminaciones son frecuentes.
¿Cuántas rotaciones necesita una sola inserción en un árbol AVL?
Se necesita como máximo una rotación - ya sea una rotación simple o una doble (de dos pasos) - para reequilibrar el árbol tras insertar un valor. Esto se debe a que una inserción aumenta la altura de un subárbol en como mucho uno, así que una única corrección en el ancestro desequilibrado más bajo basta. La eliminación es diferente: puede requerir hasta O(log n) rotaciones a medida que el reequilibrio se propaga hacia la raíz.
¿Necesito actualizar las alturas de los nodos después de cada rotación?
Sí - un error común es rotar los punteros correctamente pero olvidar recalcular la altura de los dos nodos implicados. Después de cada rotación debes actualizar primero la altura del nodo degradado y luego la del nodo promovido, porque la altura del nodo promovido depende de sus nuevos hijos. Omitir esto deja factores de equilibrio obsoletos que rompen las decisiones de reequilibrio futuras.
Coddy programming languages illustration

Domina los algoritmos con Coddy

COMENZAR