Implementación de Lista Doblemente Enlazada en Java
El objetivo es modificar una lista enlazada simple para convertirla en una lista doblemente enlazada. Esta nueva estructura incluirá una referencia tanto a la cabeza (primer elemento) como a la cola (último elemento). Se implementarán las operaciones básicas como añadir, recorrer, buscar, insertar y borrar elementos.
Clase Nodo
Representa cada elemento individual dentro de la lista doblemente enlazada.
// Clase Nodo que representa cada elemento de la lista doblemente enlazada
class Nodo {
int dato; // Almacena el dato del nodo
Nodo siguiente; // Referencia al siguiente nodo de la lista
Nodo anterior; // Referencia al nodo anterior en la lista
// Constructor del nodo que inicializa el dato y las referencias a siguiente y anterior como null
public Nodo(int dato) {
this.dato = dato;
this.siguiente = null;
this.anterior = null;
}
}
Clase MainListaDobleEnlazadaEnteros
Clase principal que gestiona la lógica y las operaciones de la lista doblemente enlazada.
public class MainListaDobleEnlazadaEnteros {
private Nodo cabeza; // Referencia al primer nodo de la lista (cabeza)
private Nodo cola; // Referencia al último nodo de la lista (cola)
// Constructor de la lista que inicializa la cabeza y la cola como null
public MainListaDobleEnlazadaEnteros() {
this.cabeza = null;
this.cola = null;
}
Método: Añadir al Final (aniadirAlFinal
)
Añade un nuevo nodo con el dato especificado al final de la lista.
// Método para añadir un nodo al final de la lista
public void aniadirAlFinal(int dato) {
Nodo nuevoNodo = new Nodo(dato); // Creamos un nuevo nodo con el dato proporcionado
if (cabeza == null) {
// Si la lista está vacía, el nuevo nodo será tanto la cabeza como la cola
cabeza = nuevoNodo;
cola = nuevoNodo;
} else {
cola.siguiente = nuevoNodo; // El siguiente de la cola actual será el nuevo nodo
nuevoNodo.anterior = cola; // El anterior del nuevo nodo será la cola actual
cola = nuevoNodo; // La cola ahora será el nuevo nodo
}
}
Método: Añadir al Principio (aniadirAlPrincipio
)
Añade un nuevo nodo con el dato especificado al inicio de la lista.
// Método para añadir un nodo al inicio de la lista
public void aniadirAlPrincipio(int dato) {
Nodo nuevoNodo = new Nodo(dato); // Creamos un nuevo nodo con el dato proporcionado
if (cabeza == null) {
// Si la lista está vacía, el nuevo nodo será tanto la cabeza como la cola
cabeza = nuevoNodo;
cola = nuevoNodo;
} else {
nuevoNodo.siguiente = cabeza; // El siguiente del nuevo nodo será la cabeza actual
cabeza.anterior = nuevoNodo; // El anterior de la cabeza será el nuevo nodo
cabeza = nuevoNodo; // La cabeza ahora será el nuevo nodo
}
}
Método: Recorrer Lista (recorrerLista
)
Recorre la lista desde la cabeza hasta la cola e imprime los datos de cada nodo.
// Método para recorrer la lista e imprimir los datos de los nodos
public void recorrerLista() {
Nodo actual = cabeza; // Empezamos desde la cabeza
while (actual != null) { // Mientras no lleguemos al final de la lista
System.out.print(actual.dato + " "); // Imprimimos el dato del nodo actual
actual = actual.siguiente; // Nos movemos al siguiente nodo
}
System.out.println(); // Nueva línea después de imprimir toda la lista
}
Método: Verificar Existencia (existeElemento
)
Comprueba si un elemento con el dato especificado existe en la lista.
// Método para verificar si un dato existe en la lista
public boolean existeElemento(int dato) {
Nodo actual = cabeza; // Empezamos desde la cabeza
while (actual != null) { // Recorremos toda la lista
if (actual.dato == dato) { // Si encontramos el dato
return true; // Retornamos true
}
actual = actual.siguiente; // Continuamos al siguiente nodo
}
return false; // Si no encontramos el dato, retornamos false
}
Método: Insertar Después De (insertaElementoDespuesDe
)
Inserta un nuevo nodo con datoAInsertar
inmediatamente después del primer nodo que contenga datoABuscar
.
// Método para insertar un elemento después de un dato específico
public boolean insertaElementoDespuesDe(int datoABuscar, int datoAInsertar) {
Nodo actual = cabeza; // Empezamos desde la cabeza
while (actual != null) { // Recorremos la lista
if (actual.dato == datoABuscar) { // Si encontramos el dato que buscamos
Nodo nuevoNodo = new Nodo(datoAInsertar); // Creamos un nuevo nodo con el dato a insertar
nuevoNodo.siguiente = actual.siguiente; // El siguiente nodo del nuevo nodo será el que sigue al actual
if (actual.siguiente != null) {
actual.siguiente.anterior = nuevoNodo; // Si el nodo actual no es el último, el anterior del siguiente nodo será el nuevo nodo
} else {
cola = nuevoNodo; // Si el nodo actual es el último, el nuevo nodo será la cola
}
actual.siguiente = nuevoNodo; // Insertamos el nuevo nodo después del nodo actual
nuevoNodo.anterior = actual; // El anterior del nuevo nodo será el nodo actual
return true; // Retornamos true porque la inserción fue exitosa
}
actual = actual.siguiente; // Continuamos al siguiente nodo
}
return false; // Si no encontramos el datoABuscar, retornamos false
}
Método: Borrar Elemento (borraElemento
)
Elimina el primer nodo que contenga el dato especificado.
// Método para borrar el primer elemento con el dato dado
public boolean borraElemento(int dato) {
if (cabeza == null) { // Si la lista está vacía, no se puede borrar nada
return false;
}
// Caso 1: El elemento a borrar está en la cabeza
if (cabeza.dato == dato) {
if (cabeza.siguiente != null) {
cabeza = cabeza.siguiente; // La cabeza ahora será el siguiente nodo
cabeza.anterior = null; // El anterior de la nueva cabeza será null
} else {
// Si solo hay un nodo, la lista quedará vacía
cabeza = null;
cola = null; // La cola también será null
}
return true;
}
// Caso 2: El elemento está en otro lugar (o no está)
Nodo actual = cabeza; // Empezamos desde la cabeza (ya sabemos que no es el primer nodo)
while (actual != null) { // Recorremos la lista
if (actual.dato == dato) { // Si encontramos el dato en el nodo actual
// Actualizar el enlace 'siguiente' del nodo anterior
if (actual.anterior != null) { // No debería ser null porque ya comprobamos la cabeza
actual.anterior.siguiente = actual.siguiente;
}
// Actualizar el enlace 'anterior' del nodo siguiente y la cola si es necesario
if (actual.siguiente != null) {
actual.siguiente.anterior = actual.anterior;
} else {
// Si el nodo actual es la cola, actualizamos la cola
cola = actual.anterior;
}
// No es necesario actualizar la cabeza aquí porque ya se manejó el caso 1
return true; // Retornamos true porque la eliminación fue exitosa
}
actual = actual.siguiente; // Continuamos al siguiente nodo
}
return false; // Si no encontramos el dato, retornamos false
}
Ejemplo de Uso (Método main
)
Demostración de cómo utilizar la clase MainListaDobleEnlazadaEnteros
y sus métodos.
// Método principal para probar la lista doblemente enlazada
public static void main(String[] args) {
MainListaDobleEnlazadaEnteros lista = new MainListaDobleEnlazadaEnteros(); // Creamos una nueva lista doblemente enlazada
lista.aniadirAlFinal(10); // Añadimos un nodo con valor 10 al final
lista.aniadirAlFinal(20); // Añadimos un nodo con valor 20 al final
lista.aniadirAlPrincipio(5); // Añadimos un nodo con valor 5 al principio
System.out.print("Lista actual: ");
lista.recorrerLista(); // Imprime: 5 10 20
System.out.println("¿Existe el 10? " + lista.existeElemento(10)); // Imprime: true
System.out.println("¿Existe el 15? " + lista.existeElemento(15)); // Imprime: false
System.out.println("Insertando 15 después del 10...");
lista.insertaElementoDespuesDe(10, 15); // Inserta 15 después del 10
System.out.print("Lista después de insertar: ");
lista.recorrerLista(); // Imprime: 5 10 15 20
System.out.println("Borrando el 10...");
lista.borraElemento(10); // Borra el nodo con valor 10
System.out.print("Lista después de borrar: ");
lista.recorrerLista(); // Imprime: 5 15 20
}
} // Fin de la clase MainListaDobleEnlazadaEnteros