Pilas en Python
Una pila (stack) es una estructura de datos que sigue el principio LIFO (Last In, First Out), lo que significa que el último elemento en entrar es el primero en salir.
Concepto básico
Imagina una pila de platos:
Los nuevos platos se colocan en la cima de la pila
Los platos se retiran desde la cima de la pila
Implementaciones en Python
1. Usando listas (Recomendado para pilas)
# Crear una pila vacía
pila = []
# Agregar elementos a la cima (push)
pila.append("A")
pila.append("B")
pila.append("C")
print(f"Pila: {pila}") # Pila: ['A', 'B', 'C']
# Eliminar el elemento de la cima (pop)
elemento_cima = pila.pop()
print(f"Elemento eliminado: {elemento_cima}") # Elemento eliminado: C
print(f"Pila después de pop: {pila}") # Pila después de pop: ['A', 'B']
# Ver el elemento de la cima sin eliminarlo
print(f"Elemento en la cima: {pila[-1]}") # Elemento en la cima: B2. Usando collections.deque
from collections import deque
# Crear una pila
pila = deque()
# Push - agregar elementos
pila.append("X")
pila.append("Y")
pila.append("Z")
print(f"Pila: {list(pila)}") # Pila: ['X', 'Y', 'Z']
# Pop - eliminar de la cima
elemento = pila.pop()
print(f"Elemento eliminado: {elemento}") # Elemento eliminado: Z
# Ver la cima
print(f"Cima: {pila[-1]}") # Cima: YOperaciones principales
pila = []
# 1. Push - agregar elemento a la cima
pila.append(10)
pila.append(20)
pila.append(30)
print(f"Pila después de push: {pila}") # [10, 20, 30]
# 2. Pop - eliminar elemento de la cima
print(f"Pop: {pila.pop()}") # 30
print(f"Pila después de pop: {pila}") # [10, 20]
# 3. Peek/Top - ver elemento de la cima sin eliminar
print(f"Cima: {pila[-1]}") # 20
# 4. Tamaño de la pila
print(f"Tamaño: {len(pila)}") # 2
# 5. Verificar si está vacía
print(f"¿Está vacía? {len(pila) == 0}") # False
# 6. Limpiar la pila
pila.clear()
print(f"¿Está vacía después de clear? {len(pila) == 0}") # TrueEjemplo práctico: Historial de navegación
class HistorialNavegacion:
def __init__(self):
self.pila_historial = []
self.pila_avance = [] # Para la funcionalidad de avance
def visitar_pagina(self, url):
"""Agrega una nueva página al historial"""
self.pila_historial.append(url)
self.pila_avance.clear() # Limpiar pila de avance al visitar nueva página
print(f"🌐 Visitando: {url}")
def retroceder(self):
"""Retrocede a la página anterior"""
if len(self.pila_historial) > 1:
pagina_actual = self.pila_historial.pop()
self.pila_avance.append(pagina_actual)
pagina_anterior = self.pila_historial[-1]
print(f"◀️ Retrocediendo a: {pagina_anterior}")
return pagina_anterior
else:
print("🚫 No hay páginas anteriores")
return None
def avanzar(self):
"""Avanza a la página siguiente"""
if self.pila_avance:
pagina = self.pila_avance.pop()
self.pila_historial.append(pagina)
print(f"▶️ Avanzando a: {pagina}")
return pagina
else:
print("🚫 No hay páginas siguientes")
return None
def pagina_actual(self):
"""Muestra la página actual"""
if self.pila_historial:
return self.pila_historial[-1]
return None
def mostrar_historial(self):
"""Muestra todo el historial"""
print(f"📚 Historial: {self.pila_historial}")
print(f"🔜 Páginas para avanzar: {self.pila_avance}")
# Uso del historial
navegador = HistorialNavegacion()
navegador.visitar_pagina("google.com")
navegador.visitar_pagina("youtube.com")
navegador.visitar_pagina("github.com")
print(f"Página actual: {navegador.pagina_actual()}") # github.com
navegador.retroceder() # Retrocede a youtube.com
navegador.retroceder() # Retrocede a google.com
navegador.avanzar() # Avanza a youtube.com
navegador.mostrar_historial()Ejemplo: Sistema de deshacer/rehacer
class EditorTexto:
def __init__(self):
self.pila_deshacer = []
self.pila_rehacer = []
self.texto = ""
def escribir(self, nuevo_texto):
"""Agrega texto y guarda estado anterior"""
if self.texto != nuevo_texto:
self.pila_deshacer.append(self.texto)
self.texto = nuevo_texto
self.pila_rehacer.clear() # Limpiar rehacer al hacer nueva acción
print(f"✏️ Texto actual: '{self.texto}'")
def deshacer(self):
"""Deshace la última acción"""
if self.pila_deshacer:
estado_anterior = self.pila_deshacer.pop()
self.pila_rehacer.append(self.texto)
self.texto = estado_anterior
print(f"↩️ Deshacer: '{self.texto}'")
else:
print("🚫 Nada para deshacer")
def rehacer(self):
"""Rehace la última acción deshecha"""
if self.pila_rehacer:
estado_siguiente = self.pila_rehacer.pop()
self.pila_deshacer.append(self.texto)
self.texto = estado_siguiente
print(f"↪️ Rehacer: '{self.texto}'")
else:
print("🚫 Nada para rehacer")
# Uso del editor
editor = EditorTexto()
editor.escribir("Hola")
editor.escribir("Hola mundo")
editor.escribir("Hola mundo Python")
editor.deshacer() # Vuelve a "Hola mundo"
editor.deshacer() # Vuelve a "Hola"
editor.rehacer() # Vuelve a "Hola mundo"Aplicaciones comunes de las pilas
Evaluación de expresiones matemáticas
Algoritmos de backtracking (como laberintos)
Gestión de llamadas a funciones (call stack)
Historial de navegación
Sistemas de deshacer/rehacer
Algoritmo DFS (Depth-First Search)
Ejemplo: Verificador de paréntesis balanceados
def verificar_parentesis(expresion):
"""Verifica si los paréntesis están balanceados"""
pila = []
pares = {')': '(', ']': '[', '}': '{'}
for caracter in expresion:
if caracter in '([{':
pila.append(caracter)
elif caracter in ')]}':
if not pila or pila[-1] != pares[caracter]:
return False
pila.pop()
return len(pila) == 0
# Pruebas
expresiones = [
"((2 + 3) * 5)",
"{[()()]}",
"({[}])",
"sin(x) + cos(y)",
"((())"
]
for expr in expresiones:
resultado = "✓ Balanceado" if verificar_parentesis(expr) else "✗ No balanceado"
print(f"{expr} -> {resultado}")¿Cuándo usar cada implementación?
Listas: Para la mayoría de casos, son eficientes para operaciones en un solo extremo
deque: Cuando necesitas mejor rendimiento para pilas muy grandes
LifoQueue: Cuando trabajas con múltiples hilos
Las pilas son estructuras fundamentales en programación, especialmente útiles para algoritmos recursivos, procesamiento de lenguaje natural, y cualquier situación donde necesites "deshacer" operaciones en orden inverso.
Comentarios
Publicar un comentario