5 - Operaciones fundamentales de una pila con arrays

Core de la API estática

Una pila basada en arrays debe exponer operaciones compactas y deterministas. Las siguientes subsecciones describen la implementación usual con un Stack que almacena enteros, pero la lógica se adapta fácilmente a otros tipos.

#include <stdio.h>

#define STACK_MAX 64

typedef struct {
  int datos[STACK_MAX];
  int top;
} Stack;

void stack_init(Stack *s) {
  s->top = 0;
}

5.1 Push (apilar)

Inserta un elemento en el tope, siempre que exista capacidad disponible. Devuelve un valor booleano (1 ó 0) para indicar éxito.

int stack_push(Stack *s, int valor) {
  if (s->top == STACK_MAX) {
    return 0; /* overflow */
  }
  s->datos[s->top++] = valor;
  return 1;
}

5.2 Pop (desapilar)

Remueve el elemento superior. Es aconsejable devolver el valor mediante un parámetro de salida para distinguir entre error y datos reales.

int stack_pop(Stack *s, int *out) {
  if (s->top == 0) {
    return 0; /* underflow */
  }
  *out = s->datos[--s->top];
  return 1;
}

5.3 Peek (ver el tope sin quitarlo)

Permite inspeccionar el elemento actual sin modificar el estado de la pila, ideal para validaciones o algoritmos que necesitan comparar el próximo valor.

int stack_peek(const Stack *s, int *out) {
  if (s->top == 0) {
    return 0;
  }
  *out = s->datos[s->top - 1];
  return 1;
}

5.4 isEmpty

Función auxiliar para consultar si la pila está vacía. Facilita la lectura del código y evita repetir comparaciones.

int stack_is_empty(const Stack *s) {
  return s->top == 0;
}

5.5 isFull

Complemento del anterior para detectar si la pila alcanzó la capacidad máxima. Resulta útil para interfaces que desean mostrar un mensaje al usuario antes de intentar un push.

int stack_is_full(const Stack *s) {
  return s->top == STACK_MAX;
}

5.6 Imprimir pila

Recorrer el array desde el tope hacia abajo ayuda a depurar o mostrar el contenido actual. El siguiente ejemplo muestra el formato [top: valor].

void stack_print(const Stack *s) {
  printf("Pila (%d elementos):\n", s->top);
  for (int i = s->top - 1; i >= 0; --i) {
    if (i == s->top - 1) {
      printf("  [top] %d\n", s->datos[i]);
    } else {
      printf("        %d\n", s->datos[i]);
    }
  }
}

5.7 Manejo correcto de índices

Los arrays comienzan en cero; por lo tanto, el incremento/decremento de top debe ser cuidadoso. Las reglas básicas:

  • Asignar antes de incrementar en push: s->datos[s->top++] = valor;
  • Decrementar antes de leer en pop: *out = s->datos[--s->top];
  • Validar siempre los límites con isFull e isEmpty para prevenir desbordes.

Pequeños errores en el orden de incremento/decremento pueden provocar lecturas fuera de rango y resultados erráticos. Añadir pruebas unitarias o asserts ayuda a detectar estos fallos temprano.

Código completo para CLion

El siguiente snippet combina todas las operaciones en un programa ejecutable:

#include <stdio.h>

#define STACK_MAX 6

typedef struct {
  int datos[STACK_MAX];
  int top;
} Stack;

void stack_init(Stack *s) { s->top = 0; }
int stack_is_empty(const Stack *s) { return s->top == 0; }
int stack_is_full(const Stack *s) { return s->top == STACK_MAX; }

int stack_push(Stack *s, int valor) {
  if (stack_is_full(s)) return 0;
  s->datos[s->top++] = valor;
  return 1;
}

int stack_pop(Stack *s, int *out) {
  if (stack_is_empty(s)) return 0;
  *out = s->datos[--s->top];
  return 1;
}

int stack_peek(const Stack *s, int *out) {
  if (stack_is_empty(s)) return 0;
  *out = s->datos[s->top - 1];
  return 1;
}

void stack_print(const Stack *s) {
  printf("Contenido actual:\n");
  for (int i = s->top - 1; i >= 0; --i) {
    printf("  %d%s\n", s->datos[i], i == s->top - 1 ? " <- top" : "");
  }
}

int main(void) {
  Stack pila;
  stack_init(&pila);

  for (int i = 1; i <= 4; ++i) {
    stack_push(&pila, i * 10);
  }
  stack_print(&pila);

  int peek;
  if (stack_peek(&pila, &peek)) {
    printf("Peek: %d\n", peek);
  }

  int valor;
  while (stack_pop(&pila, &valor)) {
    printf("Pop: %d\n", valor);
  }

  return 0;
}

Al compilarlo en CLion se observará la impresión del estado completo, el resultado de peek y cada pop sucesivo, validando el manejo de índices.

Salida de consola mostrando una pila con arrays en CLion