Listas Enlazadas — Método eliminarÚltimo

🧩 Implementemos eliminarÚltimo()

Ahora implementaremos el método eliminarÚltimo().
Este es uno de los más complejos, así que ¡presta atención! 👀

public void eliminarUltimo() {
    // Paso 1: verificar si la lista no está vacía
}

⚠️ Validación inicial

Antes de eliminar, debemos asegurarnos de que la lista no esté vacía.

public void eliminarUltimo() {
    if (estaVacia())
        throw new NoSuchElementException();
}

✅ Si está vacía → lanzamos una excepción controlada. Esto evita errores como NullPointerException.

🧠 Caso especial — Un solo nodo

Si la lista tiene solo un nodo, debemos dejarla vacía:

if (primero == ultimo) {
    primero = ultimo = null;
    return;
}

🎯 Así manejamos el caso más simple correctamente.

🧭 Caso general — Encontrar el nodo anterior

Necesitamos encontrar el nodo anterior al último. Para eso recorremos la lista desde el inicio:

var actual = primero;
while (actual != null) {
    if (actual.next == ultimo)
        break;
    actual = actual.next;
}

// actual ahora apunta al nodo anterior al último

Pero… este código no es muy legible 😅 Mejor lo convertimos en un método auxiliar.

🧱 Método auxiliar getAnterior()

private Nodo getAnterior(Nodo nodo) {
    var actual = primero;
    while (actual != null) {
        if (actual.next == nodo)
            return actual;
        actual = actual.next;
    }
    return null;
}

📦 Este método devuelve el nodo que está antes del que se pasa como argumento. Si no hay ninguno → devuelve null.

🧩 Usamos getAnterior() en eliminarUltimo()

var anterior = getAnterior(ultimo);
ultimo = anterior;
ultimo.next = null;

📌 Ahora ultimo apunta al nodo anterior y cortamos el enlace hacia el nodo eliminado.

📊 Visualización — Antes de eliminar

10
➡️
20
➡️
30

➡️ null

primero → 🟨10
     último → 🟩30

Queremos eliminar el último nodo (30).

🪄 Paso 1 — Encontrar el anterior

10
➡️
20
➡️
30

➡️ null

anterior → 🟦20
    último → 🟩30

🧭 Hemos localizado el nodo anterior al último.

🪄 Paso 2 — Cortar el enlace

10
➡️
20
  ✂️
30

último.next = null
🧹💨 Nodo 30 eliminado de la lista.

El recolector de basura podrá eliminar el nodo 30.

🪄 Paso 3 — Actualizar puntero último

10
➡️
20

➡️ null

primero → 🟨10
     último → 🟦20

🎯 último ahora apunta correctamente al nodo 20.

📉 Caso especial — Lista con un solo nodo

10

➡️ null

primero → 🟨10
    último → 🟨10

Al eliminar el único nodo: primero = null y último = null ✅ Lista vacía 🧺

🧱 Implementación completa

public void eliminarUltimo() {
    if (estaVacia())
        throw new NoSuchElementException();

    if (primero == ultimo) {
        primero = ultimo = null;
        return;
    }

    var anterior = getAnterior(ultimo);
    ultimo = anterior;
    ultimo.next = null;
}

🧪 Probemos nuestro código

public class Main {
    public static void main(String[] args) {
        var list = new ListaEnlazada();
        list.agregarAlFinal(10);
        list.agregarAlFinal(20);
        list.agregarAlFinal(30);
        list.eliminarUltimo();
    }
}

Después de la eliminación (revisa DEBUG):

primero → 10 → 20 → null
último  → 20