que-es-un-stack

Qué son y cómo usar las Pilas (Stack)

Una PILA, o Stack, es una colección de elementos que se utiliza para organizar y manipular elementos en un orden específico.

Una PILA también se llaman estructuras LIFO (Last-In, First-Out), porque siguen el principio de que el último elemento en ser insertado (Last-In), es el primero en ser eliminado (First-Out).

Cada vez que se inserta un nuevo elemento en la PILA, se coloca en la parte superior. Cuando se elimina un elemento, el último elemento agregado es retirado.

Esto se logra mediante dos operaciones principales:

  • Push: Agrega un elemento a la parte superior de la pila.
  • Pop: Elimina y devuelve el elemento de la parte superior de la pila.

Además de estas operaciones básicas, también se pueden realizar otras operaciones en una PILA, como verificar si está vacía o acceder al elemento superior sin eliminarlo.

Existen multiples formas de implementar una PILA. Generalmente se suele utilizar un simple Array, ya que es muy eficiente al añadir y eliminar el último elemento.

Propiedades

PropiedadPilas
Frecuencia con la que lo usarás🔻🔻
Es mutable✔️
Está ordenado✔️
Es indexable
Permite duplicados✔️

Cuando usar una Pila

Tiene sentido utilizar una PILA al almacenar elementos durante un proceso que luego vamos a desandar, por lo que es previsible que necesitemos los elementos en el orden inverso.

Una PILA se asemeja a una pila de objetos físicos, como una pila de platos, donde solo se puede acceder al elemento superior. Por ejemplo, sacas la ropa de la lavadora y la acumulas. Cuando la vuelves a coger, la coges en orden inverso.

curso-programacion-stack

Una pila con tus variables recién planchadas

A mi me gusta para ilustrar el uso de una pila, cuando desmontas una máquina. Vas quitando tornillos, y los guardas ordenados. Cuando vuelvas a montarla, vas a necesitar primero el primer tornillo que quitaste. Ahí se ve el propósito de una pila.

En informática, por ejemplo, tenemos el caso de la PILA (stack) de memoria. Cada vez que una función llama a otra, le pasa parámetros en una Pila. Cuando las funciones terminan, se necesitan los parámetros en orden inverso al que se puso.

Pero no es el único ejemplo. Siempre que tengas que guardar elementos a lo largo de un proceso, que luego tienes que recorrer en sentido inverso, es posible que te encaje una Pila.

Ejemplo de Pila en diferentes lenguajes de programación

A continuación, se presentan ejemplos de cómo se puede implementar una pila en diferentes lenguajes de programación:

C# dispone de una Pila nativa, que se llama Stack. Así que simplemente tenemos que usarla así.

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        Stack<int> pila = new Stack<int>();

        pila.Push(5);
        pila.Push(10);
        pila.Push(15);

        int elementoSuperior = pila.Pop(); // Retorna 15
        Console.WriteLine(elementoSuperior);
    }
}

C++ también dispone de una Pila nativa, que se llama stack<T>, y que podemos usar directamente,

#include <iostream>
#include <stack>
using namespace std;

int main()
{
    stack<int> pila;

    pila.push(5);
    pila.push(10);
    pila.push(15);

    int elementoSuperior = pila.top(); // Retorna 15
    pila.pop();

    cout << elementoSuperior << endl;
    return 0;
}

Por contra, JavaScript no tiene una Pila nativa. Así que podemos, o buscar alguna existente por en una biblioteca, o implementarla nosotros mismos así,

class Pila {
    constructor() {
        this.pila = [];
    }

    push(elemento) {
        this.pila.push(elemento);
    }

    pop() {
        return this.pila.pop();
    }

    peek() {
        return this.pila[this.pila.length - 1];
    }

    isEmpty() {
        return this.pila.length === 0;
    }
}

const pila = new Pila();
pila.push(5);
pila.push(10);
pila.push(15);

const elementoSuperior = pila.pop(); // Retorna 15
console.log(elementoSuperior);

Python tampoco tiene una Pila nativa. Así que podemos, o buscar alguna existente por en una biblioteca, o implementarla nosotros mismos así,

class Pila:
    def __init__(self):
        self.pila = []

    def push(self, elemento):
        self.pila.append(elemento)

    def pop(self):
        return self.pila.pop()

    def peek(self):
        return self.pila[-1]

    def is_empty(self):
        return len(self.pila) == 0

pila = Pila()
pila.push(5)
pila.push(10)
pila.push(15)

elemento_superior = pila.pop() # Retorna 15
print(elemento_superior)

En los ejemplos anteriores, se muestra cómo crear una pila utilizando las estructuras de datos proporcionadas por cada lenguaje de programación. Se realizan operaciones de inserción, eliminación y acceso al elemento superior de la pila. Conclusiones

Eficiencia

La eficiencia de una PILA tendrá que ver con la forma en la que se haya implementado internamente. Pero, vamos a considerar que se ha implementado “bien”.

La lectura y eliminación de elementos en una PILA se realizan en tiempo constante O(1), ya que se accede al último elemento agregado.

La inserción en una PILA también es eficiente, ya que se agrega al final de la pila en tiempo constante O(1).

OperaciónPila
Acceso secuencial
Acceso aleatorio
Añadir al principio
Eliminar al principio
Añadir al final🟢
Eliminar al final🟢
Inserción aleatoria
Eliminar aleatoria
Búsqueda

El resto de operaciones no tienen sentido ya que solo puedes acceder al elemento en la cima de la PILA. No puedes acceder a elementos en posiciones intermedias sin desapilar todos los elementos por encima.