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
siguientedel nuevo nodo para que apunte al nodo que actualmente es la cabeza. - Ajustar el puntero
anteriordel 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_nodoInserció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
siguientedel último nodo para que apunte al nuevo nodo. - Ajustar el puntero
anteriordel 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
siguientedel nodo anterior para que apunte al nodo siguiente del nodo a eliminar. - Ajustar el puntero
anteriordel 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 30Conclusió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
