Eliminar en un AVL combina la lógica de un BST con una pasada extra para restaurar el balance. Tras desconectar el nodo, se recalculan alturas, se detectan desbalances y se aplican las rotaciones LL, RR, LR o RL que correspondan.
NULL).Al volver de la recursión, cada nodo recalcula su altura con la fórmula conocida 1 + max(alturaIzq, alturaDer). Esta actualización es necesaria para que el factor de balance quede consistente antes de revisar un posible desbalance.
FB queda fuera de [-1, 1], el subárbol necesita una rotación.La combinación de signos determina la rotación:
typedef struct AvlNode {
int clave;
int altura;
struct AvlNode *izquierdo;
struct AvlNode *derecho;
} AvlNode;
static int alturaNodo(AvlNode *n) { return n ? n->altura : -1; }
static AvlNode *minNodo(AvlNode *n) {
while (n && n->izquierdo) n = n->izquierdo;
return n;
}
static int max(int a, int b) { return (a > b) ? a : b; }
static int factorBalance(AvlNode *n) {
if (!n) return 0;
return alturaNodo(n->izquierdo) - alturaNodo(n->derecho);
}
AvlNode *rotarDerecha(AvlNode *y);
AvlNode *rotarIzquierda(AvlNode *x);
AvlNode *eliminarAvl(AvlNode *raiz, int clave) {
if (!raiz) return NULL;
if (clave < raiz->clave) {
raiz->izquierdo = eliminarAvl(raiz->izquierdo, clave);
} else if (clave > raiz->clave) {
raiz->derecho = eliminarAvl(raiz->derecho, clave);
} else {
if (!raiz->izquierdo || !raiz->derecho) {
AvlNode *hijo = raiz->izquierdo ? raiz->izquierdo : raiz->derecho;
free(raiz);
return hijo;
} else {
AvlNode *succ = minNodo(raiz->derecho);
raiz->clave = succ->clave;
raiz->derecho = eliminarAvl(raiz->derecho, succ->clave);
}
}
raiz->altura = 1 + max(alturaNodo(raiz->izquierdo), alturaNodo(raiz->derecho));
int fb = factorBalance(raiz);
if (fb > 1 && factorBalance(raiz->izquierdo) >= 0) return rotarDerecha(raiz); /* LL */
if (fb > 1 && factorBalance(raiz->izquierdo) < 0) { /* LR */
raiz->izquierdo = rotarIzquierda(raiz->izquierdo);
return rotarDerecha(raiz);
}
if (fb < -1 && factorBalance(raiz->derecho) <= 0) return rotarIzquierda(raiz); /* RR */
if (fb < -1 && factorBalance(raiz->derecho) > 0) { /* RL */
raiz->derecho = rotarDerecha(raiz->derecho);
return rotarIzquierda(raiz);
}
return raiz;
}
Ejemplo autocontenible que inserta, elimina claves y muestra el inorden antes y después. Copia, compila y ejecuta.
#include <stdio.h>
#include <stdlib.h>
typedef struct AvlNode {
int clave;
int altura;
struct AvlNode *izquierdo;
struct AvlNode *derecho;
} AvlNode;
static int max(int a, int b) { return (a > b) ? a : b; }
static int alturaNodo(AvlNode *n) { return n ? n->altura : -1; }
static void actualizarAltura(AvlNode *n) {
if (!n) return;
n->altura = 1 + max(alturaNodo(n->izquierdo), alturaNodo(n->derecho));
}
static int factorBalance(AvlNode *n) {
if (!n) return 0;
return alturaNodo(n->izquierdo) - alturaNodo(n->derecho);
}
AvlNode *rotarDerecha(AvlNode *y) {
AvlNode *x = y->izquierdo;
AvlNode *t2 = x->derecho;
x->derecho = y;
y->izquierdo = t2;
actualizarAltura(y);
actualizarAltura(x);
return x;
}
AvlNode *rotarIzquierda(AvlNode *y) {
AvlNode *x = y->derecho;
AvlNode *t2 = x->izquierdo;
x->izquierdo = y;
y->derecho = t2;
actualizarAltura(y);
actualizarAltura(x);
return x;
}
AvlNode *crearNodo(int clave) {
AvlNode *n = malloc(sizeof(AvlNode));
if (!n) return NULL;
n->clave = clave;
n->altura = 0;
n->izquierdo = n->derecho = NULL;
return n;
}
AvlNode *minNodo(AvlNode *n) {
while (n && n->izquierdo) n = n->izquierdo;
return n;
}
AvlNode *insertarAvl(AvlNode *raiz, int clave) {
if (!raiz) return crearNodo(clave);
if (clave < raiz->clave) raiz->izquierdo = insertarAvl(raiz->izquierdo, clave);
else if (clave > raiz->clave) raiz->derecho = insertarAvl(raiz->derecho, clave);
else return raiz;
actualizarAltura(raiz);
int fb = factorBalance(raiz);
if (fb > 1 && clave < raiz->izquierdo->clave) return rotarDerecha(raiz); /* LL */
if (fb < -1 && clave > raiz->derecho->clave) return rotarIzquierda(raiz); /* RR */
if (fb > 1 && clave > raiz->izquierdo->clave) { /* LR */
raiz->izquierdo = rotarIzquierda(raiz->izquierdo);
return rotarDerecha(raiz);
}
if (fb < -1 && clave < raiz->derecho->clave) { /* RL */
raiz->derecho = rotarDerecha(raiz->derecho);
return rotarIzquierda(raiz);
}
return raiz;
}
AvlNode *eliminarAvl(AvlNode *raiz, int clave) {
if (!raiz) return NULL;
if (clave < raiz->clave) {
raiz->izquierdo = eliminarAvl(raiz->izquierdo, clave);
} else if (clave > raiz->clave) {
raiz->derecho = eliminarAvl(raiz->derecho, clave);
} else {
if (!raiz->izquierdo || !raiz->derecho) {
AvlNode *hijo = raiz->izquierdo ? raiz->izquierdo : raiz->derecho;
free(raiz);
return hijo;
} else {
AvlNode *succ = minNodo(raiz->derecho);
raiz->clave = succ->clave;
raiz->derecho = eliminarAvl(raiz->derecho, succ->clave);
}
}
actualizarAltura(raiz);
int fb = factorBalance(raiz);
if (fb > 1 && factorBalance(raiz->izquierdo) >= 0) return rotarDerecha(raiz); /* LL */
if (fb > 1 && factorBalance(raiz->izquierdo) < 0) { /* LR */
raiz->izquierdo = rotarIzquierda(raiz->izquierdo);
return rotarDerecha(raiz);
}
if (fb < -1 && factorBalance(raiz->derecho) <= 0) return rotarIzquierda(raiz); /* RR */
if (fb < -1 && factorBalance(raiz->derecho) > 0) { /* RL */
raiz->derecho = rotarDerecha(raiz->derecho);
return rotarIzquierda(raiz);
}
return raiz;
}
void imprimirInorden(AvlNode *n) {
if (!n) return;
imprimirInorden(n->izquierdo);
printf("%d ", n->clave);
imprimirInorden(n->derecho);
}
void liberar(AvlNode *n) {
if (!n) return;
liberar(n->izquierdo);
liberar(n->derecho);
free(n);
}
int main(void) {
int claves[] = {30, 20, 40, 10, 25, 50, 5, 35, 45};
int eliminar[] = {10, 40, 30};
int n1 = (int)(sizeof(claves) / sizeof(claves[0]));
int n2 = (int)(sizeof(eliminar) / sizeof(eliminar[0]));
AvlNode *raiz = NULL;
for (int i = 0; i < n1; ++i) raiz = insertarAvl(raiz, claves[i]);
printf("AVL inicial (inorden): ");
imprimirInorden(raiz);
printf("\n\n");
for (int j = 0; j < n2; ++j) {
raiz = eliminarAvl(raiz, eliminar[j]);
printf("Tras eliminar %d: ", eliminar[j]);
imprimirInorden(raiz);
printf("\n");
}
printf("AVL final: ");
imprimirInorden(raiz);
printf("\n");
liberar(raiz);
return 0;
}