C Academy · Lección

Buscar y liberar

Encuentre nodos y libere memoria

Lección 4 de 413 pasos

Buscar y liberar es una lección gratuita de C Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C Academy incluye 4 lecciones en total.

Búsqueda en un BST

La búsqueda aprovecha la regla de ordenación. En cada nodo se compara el objetivo con el valor del nodo y se avanza únicamente por uno de los subárboles.

Como se descarta la mitad de los nodos restantes en cada paso, el coste de la búsqueda depende de la altura del árbol, no de su tamaño.

Búsqueda recursiva

La búsqueda recursiva tiene dos casos base: un subárbol vacío significa que no se ha encontrado el valor y un valor coincidente significa que sí se ha encontrado.

En caso contrario, se realiza una llamada recursiva a la izquierda o a la derecha según la comparación.

Node *search(Node *root, int target) {
    if (root == NULL || root->value == target)
        return root;
    if (target < root->value)
        return search(root->left, target);
    return search(root->right, target);
}

Búsqueda iterativa

La búsqueda también puede implementarse mediante un bucle sencillo, evitando el coste adicional de la recursión.

Se siguen los punteros por el árbol hasta encontrar el objetivo o llegar al final, en NULL.

Node *search_iter(Node *root, int target) {
    while (root != NULL) {
        if (target == root->value) return root;
        root = (target < root->value)
             ? root->left : root->right;
    }
    return NULL;  /* not found */
}

La búsqueda en acción

Este programa construye un BST y busca un valor presente y otro ausente, indicando si se encontró cada uno.

Un valor de retorno distinto de NULL significa que se encontró; NULL significa que el valor no está en el árbol.

#include <stdio.h>
#include <stdlib.h>

typedef struct Node { int value; struct Node *left, *right; } Node;
Node *cn(int v){ Node *n=malloc(sizeof(Node)); n->value=v; n->left=n->right=NULL; return n; }
Node *insert(Node *r,int v){
    if(!r) return cn(v);
    if(v<r->value) r->left=insert(r->left,v);
    else if(v>r->value) r->right=insert(r->right,v);
    return r;
}
Node *search(Node *r,int t){
    if(!r||r->value==t) return r;
    return t<r->value ? search(r->left,t) : search(r->right,t);
}

int main(void){
    Node *root=NULL;
    int d[]={10,5,15,3,7};
    for(int i=0;i<5;i++) root=insert(root,d[i]);
    printf("7:%s 99:%s\n",
        search(root,7)?"found":"no",
        search(root,99)?"found":"no");
    return 0;
}

Encontrar el mínimo

En un BST, el valor más pequeño está en el nodo situado más a la izquierda: siga left hasta que sea NULL.

De forma simétrica, el máximo está en el nodo situado más a la derecha. Estas funciones auxiliares son importantes para la eliminación y las consultas por intervalos.

Node *find_min(Node *root) {
    if (root == NULL) return NULL;
    while (root->left != NULL)
        root = root->left;
    return root;
}

Por qué es importante liberar memoria

Cada nodo se obtuvo mediante malloc, por lo que cada nodo debe devolverse mediante free. Si olvida liberarlo, se produce una fuga de memoria.

Sin embargo, no puede liberar un nodo y después leer sus punteros a los hijos, por lo que el orden de liberación es fundamental.

Liberar en postorden

La forma segura de liberar un árbol es hacerlo en postorden: libere primero ambos hijos y después el propio nodo.

Esto garantiza que los punteros left y right del nodo se lean antes de liberar la memoria de dicho nodo.

void free_tree(Node *root) {
    if (root == NULL) return;
    free_tree(root->left);
    free_tree(root->right);
    free(root);
}

Un orden incorrecto peligroso

Si libera el nodo antes de realizar la llamada recursiva sobre sus hijos, provoca un comportamiento indefinido: tendría que desreferenciar memoria liberada para llegar a los subárboles.

Este es un error clásico de uso después de liberar. Libere siempre primero los hijos.

/* WRONG: use-after-free */
void bad_free(Node *root) {
    if (!root) return;
    free(root);                 /* freed here */
    bad_free(root->left);       /* reads freed memory! */
    bad_free(root->right);
}

Evitar punteros colgantes

Después de que free_tree termine, el puntero original a la raíz todavía contiene la dirección antigua, pero la memoria ya no existe.

Si lo vuelve a establecer en NULL en la función que lo llamó, evitará reutilizar accidentalmente un puntero colgante.

free_tree(root);
root = NULL;   /* avoid a dangling pointer */

Contar los nodos liberados

Podemos confirmar que la liberación funciona contando los nodos durante el recorrido en postorden y liberando después cada uno.

Este programa construye un árbol, lo libera e informa de cuántos nodos se liberaron.

#include <stdio.h>
#include <stdlib.h>

typedef struct Node { int value; struct Node *left, *right; } Node;
Node *cn(int v){ Node *n=malloc(sizeof(Node)); n->value=v; n->left=n->right=NULL; return n; }
Node *insert(Node *r,int v){
    if(!r) return cn(v);
    if(v<r->value) r->left=insert(r->left,v);
    else if(v>r->value) r->right=insert(r->right,v);
    return r;
}
int free_count(Node *r){
    if(!r) return 0;
    int c = free_count(r->left) + free_count(r->right);
    free(r);
    return c + 1;
}

int main(void){
    Node *root=NULL;
    int d[]={10,5,15,3,7};
    for(int i=0;i<5;i++) root=insert(root,d[i]);
    printf("freed=%d\n", free_count(root));
    root = NULL;
    return 0;
}

Buscar y liberar conjuntamente

Un ciclo de vida completo: construir el árbol, buscar en él y después liberarlo. Realizar las tres operaciones mantiene los programas correctos y sin fugas de memoria.

Herramientas como Valgrind pueden confirmar que cada llamada a malloc tiene su correspondiente free.

/* lifecycle
 * 1. insert values     (allocate)
 * 2. search as needed   (read-only)
 * 3. free_tree(root)    (deallocate)
 * 4. root = NULL        (avoid dangling)
 */

Comprobación rápida

Analice cómo realizar una desasignación segura.

Resumen

La búsqueda en un BST compara y avanza por un subárbol en cada paso, con un coste temporal proporcional a la altura. El mínimo es el nodo situado más a la izquierda y el máximo, el situado más a la derecha.

Libere un árbol en postorden para liberar los hijos antes que el padre y, después, establezca la raíz en NULL para evitar un puntero colgante.

Gratis para empezar

Aprende C con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
39
Lecciones
144

Preguntas frecuentes

¿La lección «Buscar y liberar» es gratis?

Sí — el texto completo de «Buscar y liberar» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C Academy, actualiza a CoddyKit PRO. El curso de C Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Buscar y liberar»?

Encuentre nodos y libere memoria Practicas C Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C Academy?

No se requiere experiencia previa. C Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Buscar y liberar»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C Academy?

Sí. Cada lección de C Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Nodos y estructura de árboles
  2. Insertar en un BST
  3. Recorridos
  4. Buscar y liberar
← Volver a C Academy