Introducción
Las listas doblemente enlazadas son una extensión de las listas enlazadas simples. En una lista doblemente enlazada, cada nodo contiene dos punteros: uno que apunta al siguiente nodo en la secuencia y otro que apunta al nodo anterior. Esta estructura permite una navegación bidireccional, lo que facilita ciertas operaciones como la inserción y eliminación de nodos.
Estructura de un Nodo en una Lista Doblemente Enlazada
Cada nodo en una lista doblemente enlazada contiene tres componentes principales:
- Dato: El valor almacenado en el nodo.
- Puntero al siguiente nodo: Un enlace al siguiente nodo en la lista.
- Puntero al nodo anterior: Un enlace al nodo anterior en la lista.
Representación en Python
Operaciones Básicas
- Inserción
Inserción al Inicio
Para insertar un nodo al inicio de la lista:
- Crear un nuevo nodo.
- Ajustar el puntero
siguiente
del nuevo nodo para que apunte al nodo que actualmente es la cabeza. - Ajustar el puntero
anterior
del nodo que actualmente es la cabeza para que apunte al nuevo nodo. - Actualizar la cabeza de la lista para que sea el nuevo nodo.
class ListaDobleEnlazada: def __init__(self): self.cabeza = None def insertar_inicio(self, dato): nuevo_nodo = Nodo(dato) if self.cabeza is not None: nuevo_nodo.siguiente = self.cabeza self.cabeza.anterior = nuevo_nodo self.cabeza = nuevo_nodo
Inserción al Final
Para insertar un nodo al final de la lista:
- Crear un nuevo nodo.
- Recorrer la lista hasta llegar al último nodo.
- Ajustar el puntero
siguiente
del último nodo para que apunte al nuevo nodo. - Ajustar el puntero
anterior
del nuevo nodo para que apunte al último nodo.
def insertar_final(self, dato): nuevo_nodo = Nodo(dato) if self.cabeza is None: self.cabeza = nuevo_nodo return ultimo = self.cabeza while ultimo.siguiente: ultimo = ultimo.siguiente ultimo.siguiente = nuevo_nodo nuevo_nodo.anterior = ultimo
- Eliminación
Eliminación de un Nodo Específico
Para eliminar un nodo específico:
- Encontrar el nodo que contiene el dato a eliminar.
- Ajustar el puntero
siguiente
del nodo anterior para que apunte al nodo siguiente del nodo a eliminar. - Ajustar el puntero
anterior
del nodo siguiente para que apunte al nodo anterior del nodo a eliminar.
def eliminar_nodo(self, dato): actual = self.cabeza while actual: if actual.dato == dato: if actual.anterior: actual.anterior.siguiente = actual.siguiente if actual.siguiente: actual.siguiente.anterior = actual.anterior if actual == self.cabeza: self.cabeza = actual.siguiente return actual = actual.siguiente
- Recorrido
Recorrido hacia Adelante
Para recorrer la lista hacia adelante:
- Comenzar desde la cabeza.
- Continuar moviéndose al siguiente nodo hasta llegar al final de la lista.
def recorrer_adelante(self): actual = self.cabeza while actual: print(actual.dato, end=' ') actual = actual.siguiente print()
Recorrido hacia Atrás
Para recorrer la lista hacia atrás:
- Comenzar desde el último nodo.
- Continuar moviéndose al nodo anterior hasta llegar al inicio de la lista.
def recorrer_atras(self): actual = self.cabeza if actual is None: return while actual.siguiente: actual = actual.siguiente while actual: print(actual.dato, end=' ') actual = actual.anterior print()
Ejemplo Completo
A continuación, se muestra un ejemplo completo que incluye la creación de una lista doblemente enlazada, la inserción de nodos al inicio y al final, la eliminación de un nodo y el recorrido de la lista en ambas direcciones.
class Nodo: def __init__(self, dato): self.dato = dato self.siguiente = None self.anterior = None class ListaDobleEnlazada: def __init__(self): self.cabeza = None def insertar_inicio(self, dato): nuevo_nodo = Nodo(dato) if self.cabeza is not None: nuevo_nodo.siguiente = self.cabeza self.cabeza.anterior = nuevo_nodo self.cabeza = nuevo_nodo def insertar_final(self, dato): nuevo_nodo = Nodo(dato) if self.cabeza is None: self.cabeza = nuevo_nodo return ultimo = self.cabeza while ultimo.siguiente: ultimo = ultimo.siguiente ultimo.siguiente = nuevo_nodo nuevo_nodo.anterior = ultimo def eliminar_nodo(self, dato): actual = self.cabeza while actual: if actual.dato == dato: if actual.anterior: actual.anterior.siguiente = actual.siguiente if actual.siguiente: actual.siguiente.anterior = actual.anterior if actual == self.cabeza: self.cabeza = actual.siguiente return actual = actual.siguiente def recorrer_adelante(self): actual = self.cabeza while actual: print(actual.dato, end=' ') actual = actual.siguiente print() def recorrer_atras(self): actual = self.cabeza if actual is None: return while actual.siguiente: actual = actual.siguiente while actual: print(actual.dato, end=' ') actual = actual.anterior print() # Ejemplo de uso lista = ListaDobleEnlazada() lista.insertar_inicio(10) lista.insertar_inicio(20) lista.insertar_final(30) lista.recorrer_adelante() # Salida: 20 10 30 lista.recorrer_atras() # Salida: 30 10 20 lista.eliminar_nodo(10) lista.recorrer_adelante() # Salida: 20 30
Conclusión
Las listas doblemente enlazadas son una estructura de datos versátil que permite una navegación bidireccional, facilitando operaciones como la inserción y eliminación de nodos. Aunque son más complejas que las listas enlazadas simples debido a la necesidad de manejar dos punteros por nodo, ofrecen una mayor flexibilidad y eficiencia en ciertas situaciones.
En el próximo tema, exploraremos las listas circulares, una variación interesante de las listas enlazadas.
Curso de Estructuras de Datos
Módulo 1: Introducción a las Estructuras de Datos
- ¿Qué son las Estructuras de Datos?
- Importancia de las Estructuras de Datos en la Programación
- Tipos de Estructuras de Datos
Módulo 2: Listas
- Introducción a las Listas
- Listas Enlazadas
- Listas Doblemente Enlazadas
- Listas Circulares
- Ejercicios con Listas
Módulo 3: Pilas
- Introducción a las Pilas
- Operaciones Básicas con Pilas
- Implementación de Pilas
- Aplicaciones de las Pilas
- Ejercicios con Pilas
Módulo 4: Colas
- Introducción a las Colas
- Operaciones Básicas con Colas
- Colas Circulares
- Colas de Prioridad
- Ejercicios con Colas
Módulo 5: Árboles
- Introducción a los Árboles
- Árboles Binarios
- Árboles Binarios de Búsqueda
- Árboles AVL
- Árboles B
- Ejercicios con Árboles
Módulo 6: Grafos
- Introducción a los Grafos
- Representación de Grafos
- Algoritmos de Búsqueda en Grafos
- Algoritmos de Caminos Mínimos
- Aplicaciones de los Grafos
- Ejercicios con Grafos