Guía paso a paso · Estructuras Avanzadas de Pilas

La pila secuencial: un arreglo, un índice y una regla

Recorre el programa PilaSecuencial línea por línea. La animación muestra qué pasa dentro del arreglo y con el tope en cada instrucción. Después encontrarás el código comentado, los conceptos y el porqué de cada decisión.

Universidad Surcolombiana · Tecnología en Desarrollo de Software
1 · Ejecución animada

Mira el programa correr

Usa Siguiente o las flechas del teclado. La línea resaltada es la que Python está ejecutando.

Memoria · self.arregloTraza del programa
índice 0 = fondocima ↑
Variables
Consola

Modo libre · experimenta con la pila

Parte del estado actual de la traza. Intenta llenar las 5 casillas y hacer un push más, o vaciarla y hacer pop: verás el OverflowError y el IndexError.

2 · Código comentado

Cada línea, con su intención

3 · Conceptos

Lo que hay que entender

TAD Pila

LIFO: último en entrar, primero en salir

Una pila solo permite trabajar por un extremo, la cima. Como una torre de platos: el último que pones es el primero que retiras. Por eso pop() devolvió “Paciente C” y no “Paciente A”.

Representación

Secuencial (estática)

Los elementos viven en un arreglo de tamaño fijo, en posiciones contiguas 0, 1, 2… La alternativa es la representación enlazada (nodos con referencias), que crece sin límite pero usa más memoria por elemento.

Atributo tope

Un índice que marca la cima

tope guarda la posición del último elemento. No se mueven los datos: solo se mueve este índice. Con él se deducen todos los estados: vacía (-1), llena (capacidad-1) y cantidad de elementos (tope+1).

Errores de frontera

Desbordamiento y subdesbordamiento

Overflow: insertar en una pila llena. Underflow: sacar de una pila vacía. Son los dos casos límite de toda estructura estática y el programa los detecta antes de tocar el arreglo.

POO

Encapsulamiento

La clase agrupa datos (capacidad, arreglo, tope) y operaciones. Quien usa turnos solo llama push, pop y peek; no necesita saber cómo se guarda cada dato.

Operaciones

pop() vs peek()

Ambas devuelven la cima. pop() la retira y baja el tope; peek() solo la consulta y deja la pila intacta. Por eso tras pop() el peek() mostró “Paciente B”.

OperaciónQué haceComplejidadPor qué
push(dato)Inserta en la cimaO(1)Un incremento y una asignación por índice, sin importar cuántos datos haya.
pop()Retira y devuelve la cimaO(1)Lee, limpia y decrementa: siempre tres pasos.
peek()Devuelve la cima sin retirarlaO(1)Acceso directo arreglo[tope].
esta_llena() / esta_vacia()Consultan el estadoO(1)Una sola comparación con tope.
EspacioMemoria reservadaO(n)Se reservan capacidad casillas desde el inicio, aunque estén vacías.
4 · El porqué

Decisiones de diseño del programa

¿Por qué tope = -1 al inicio?

El primer elemento irá en el índice 0. Si el tope empieza en -1, el patrón “sube el tope y luego guarda” funciona igual para el primer dato y para todos los demás. Además -1 no es un índice válido del arreglo, así que sirve como señal de “vacía”.

¿Por qué [None] * capacidad y no una lista vacía con append?

Las listas de Python crecen solas y ocultarían el límite. Reservar las casillas desde el principio simula un arreglo estático como los de C o Java, que es justo lo que se quiere estudiar: memoria fija, acceso por índice y riesgo de desbordamiento.

¿Por qué esta_llena compara con capacidad - 1?

Con capacidad 5 los índices válidos son 0 a 4. La pila está llena cuando el tope apunta a la última casilla, la 4, es decir capacidad - 1.

¿Por qué validar antes de modificar?

Si push subiera el tope y luego fallara, la pila quedaría en un estado inconsistente. Revisar primero garantiza que una operación fallida no deja rastros.

¿Por qué el orden cambia entre push y pop?

push: primero sube el tope (a una casilla libre) y luego guarda. pop: primero lee el dato, luego limpia y al final baja el tope. Si pop bajara el tope primero, leería el elemento equivocado.

¿Por qué poner None al hacer pop?

No es obligatorio: bastaría con bajar el tope. Limpiar la casilla elimina la referencia al objeto para que el recolector de basura pueda liberarlo y deja la memoria “limpia” al depurar o visualizar.

¿Por qué lanzar excepciones en lugar de devolver None?

None podría ser un dato legítimo guardado en la pila. Una excepción avisa sin ambigüedad y obliga a quien usa la pila a manejar el error (try/except). Se usan tipos estándar: OverflowError para exceso e IndexError para acceso fuera de rango.

Para discutir en clase: ¿una pila para turnos de pacientes?

El ejemplo sirve para ver el mecanismo, pero en un consultorio o en la fila de un hospital del Huila el primer paciente en llegar debe ser el primero en ser atendido. Eso es FIFO, una cola. Con la pila, “Paciente A” sería atendido de último. Una pila sí encaja con el botón Deshacer de un editor, el historial Atrás del navegador o la pila de llamadas de funciones en Python.

5 · Practica

Ejercicios

  1. Predice la salida si después del programa se ejecutan turnos.pop() dos veces más y luego turnos.peek(). Compruébalo en el modo libre.
  2. Agrega el método tamano() que devuelva cuántos elementos hay, sin recorrer el arreglo. (Pista: usa el tope.)
  3. Escribe un método __str__ que muestre la pila desde la cima hasta el fondo.
  4. Envuelve un push en try/except OverflowError para mostrar “No hay cupos disponibles” en lugar de detener el programa.
  5. Implementa ColaSecuencial con frente y final y úsala para los turnos. ¿Qué problema aparece al desencolar y cómo lo resuelve una cola circular?