Lista doblemente enlazada en C: ejercicio resuelto con inserción y recorrido

  3 minutos

Si buscas lista doblemente enlazada en C ejercicio resuelto, este ejemplo te enseña exactamente lo que suele pedirse en prácticas, entrevistas y exámenes: insertar nodos, recorrer en ambos sentidos y liberar memoria correctamente.

Implementa una lista doblemente enlazada con nodos que incluyan:

  • valor
  • puntero siguiente
  • puntero anterior

Crea funciones para:

  • insertar al final,
  • recorrer hacia adelante,
  • recorrer hacia atras,
  • liberar toda la lista.
#include <stdio.h>
#include <stdlib.h>

typedef struct Nodo {
    int valor;
    struct Nodo *siguiente;
    struct Nodo *anterior;
} Nodo;

Nodo *insertar_final(Nodo *cabeza, int valor) {
    Nodo *nuevo = (Nodo *)malloc(sizeof(Nodo));
    if (nuevo == NULL) {
        fprintf(stderr, "Error al reservar memoria.\n");
        return cabeza;
    }

    nuevo->valor = valor;
    nuevo->siguiente = NULL;
    nuevo->anterior = NULL;

    if (cabeza == NULL) {
        return nuevo;
    }

    Nodo *actual = cabeza;
    while (actual->siguiente != NULL) {
        actual = actual->siguiente;
    }

    actual->siguiente = nuevo;
    nuevo->anterior = actual;
    return cabeza;
}

Nodo *obtener_ultimo(Nodo *cabeza) {
    if (cabeza == NULL) {
        return NULL;
    }

    while (cabeza->siguiente != NULL) {
        cabeza = cabeza->siguiente;
    }

    return cabeza;
}

void recorrer_adelante(Nodo *cabeza) {
    printf("Recorrido hacia adelante:\n");
    while (cabeza != NULL) {
        printf("%d ", cabeza->valor);
        cabeza = cabeza->siguiente;
    }
    printf("\n");
}

void recorrer_atras(Nodo *cola) {
    printf("Recorrido hacia atras:\n");
    while (cola != NULL) {
        printf("%d ", cola->valor);
        cola = cola->anterior;
    }
    printf("\n");
}

void liberar_lista(Nodo *cabeza) {
    while (cabeza != NULL) {
        Nodo *tmp = cabeza;
        cabeza = cabeza->siguiente;
        free(tmp);
    }
}

int main(void) {
    Nodo *lista = NULL;

    lista = insertar_final(lista, 10);
    lista = insertar_final(lista, 20);
    lista = insertar_final(lista, 30);

    recorrer_adelante(lista);
    recorrer_atras(obtener_ultimo(lista));

    liberar_lista(lista);
    return 0;
}
Recorrido hacia adelante:
10 20 30
Recorrido hacia atras:
30 20 10
  • insertar_final: O(n) por recorrer hasta la cola.
  • recorrer_adelante y recorrer_atras: O(n).
  • Espacio extra: O(1) aparte de los nodos.
  • No actualizar anterior al enlazar el nuevo nodo.
  • Perder la referencia de cabeza.
  • No liberar la memoria al final.

Este patrón se usa mucho en problemas actuales de procesamiento de eventos (logs, colas de cambios, historicos) donde necesitas navegar hacia delante y hacia atras en la secuencia.

Si quieres una ruta completa con progresión real de dificultad:

Es nivel intermedio-alto. Si ya dominas punteros basicos, es un siguiente paso natural.

En Programación en C en 100 ejercicios resueltos y en la sección Ejercicios C. También puedes leerlo en Kindle Unlimited: Ver en Amazon.

Empieza con entradas pequeñas, prueba casos límite (vacío, un elemento y capacidad máxima) y luego reescribe la solución sin copiarla.