Los árboles AVL son la primera familia de árboles de búsqueda balanceados diseñada para mantener altura logarítmica. Cada nodo almacena su altura y exige que el factor de balance permanezca en el rango [-1, 1]. Cuando se viola esa condición, se aplican rotaciones para restaurar el equilibrio.
O(log n), garantizando búsquedas, inserciones y eliminaciones rápidas.El nodo conserva la clave, la altura precomputada y los punteros a los hijos. Es común guardar también un puntero al padre, pero no es obligatorio para las operaciones básicas.
typedef struct AvlNode {
int clave;
int altura;
struct AvlNode *izquierdo;
struct AvlNode *derecho;
} AvlNode;
AvlNode *crearNodoAvl(int clave) {
AvlNode *n = malloc(sizeof(AvlNode));
if (!n) return NULL;
n->clave = clave;
n->altura = 0; /* hoja */
n->izquierdo = n->derecho = NULL;
return n;
}
Guardar la altura en cada nodo permite recalcular rápido después de una inserción o rotación. Un nodo nulo usa altura -1, de modo que una hoja quede en 0.
static int max(int a, int b) { return (a > b) ? a : b; }
int alturaNodoAvl(AvlNode *nodo) {
return nodo ? nodo->altura : -1;
}
void actualizarAltura(AvlNode *nodo) {
if (!nodo) return;
int hIzq = alturaNodoAvl(nodo->izquierdo);
int hDer = alturaNodoAvl(nodo->derecho);
nodo->altura = 1 + max(hIzq, hDer);
}
Al actualizar la altura desde la rama que se modifica hacia la raíz, mantenemos listo el dato para evaluar el factor de balance en O(1).
El factor de balance (FB) es la resta entre la altura del subárbol izquierdo y el derecho. Si el valor cae fuera de [-1, 1], el nodo requiere rotación.
int factorBalanceAvl(AvlNode *nodo) {
if (!nodo) return 0;
return alturaNodoAvl(nodo->izquierdo) - alturaNodoAvl(nodo->derecho);
}
El FB guía la elección de rotación: LL y RR para desbalances simples, LR y RL para desbalances en zig-zag. En el siguiente tema aplicaremos este cálculo a la inserción y eliminación.