How do you implement a stack using an array in C?
A stack is a Last-In-First-Out (LIFO) data structure. An array-based stack uses:
- A fixed-size array to store elements
- A
topindex that tracks the position of the topmost element (-1 means empty)
Operations:
- push: Increment
top, place element atarr[top]. O(1) - pop: Return
arr[top], decrementtop. O(1) - peek: Return
arr[top]without modifyingtop. O(1) - isEmpty: Check if
top == -1. O(1) - isFull: Check if
top == capacity - 1. O(1)
Advantages: Simple, cache-friendly (contiguous memory), no allocation overhead per operation. Disadvantages: Fixed size (must know max capacity), or use realloc for dynamic sizing.
Stack structure:
int arr[MAX]
int top = -1
Push(stack, value):
if top == MAX-1: overflow error
top++
arr[top] = value
Pop(stack):
if top == -1: underflow error
value = arr[top]
top--
return value
Peek(stack):
if top == -1: error
return arr[top]
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
typedef struct {
int arr[MAX_SIZE];
int top;
} Stack;
void initStack(Stack *s) {
s->top = -1;
}
int isEmpty(Stack *s) {
return s->top == -1;
}
int isFull(Stack *s) {
return s->top == MAX_SIZE - 1;
}
void push(Stack *s, int val) {
if (isFull(s)) {
fprintf(stderr, "Stack overflow\n");
return;
}
s->arr[++(s->top)] = val;
}
int pop(Stack *s) {
if (isEmpty(s)) {
fprintf(stderr, "Stack underflow\n");
return -1; /* sentinel value */
}
return s->arr[(s->top)--];
}
int peek(Stack *s) {
if (isEmpty(s)) {
fprintf(stderr, "Stack is empty\n");
return -1;
}
return s->arr[s->top];
}
int main(void) {
Stack s;
initStack(&s);
push(&s, 10);
push(&s, 20);
push(&s, 30);
printf("Top: %d\n", peek(&s)); /* 30 */
printf("Pop: %d\n", pop(&s)); /* 30 */
printf("Pop: %d\n", pop(&s)); /* 20 */
printf("Empty: %d\n", isEmpty(&s)); /* 0 (false) */
printf("Pop: %d\n", pop(&s)); /* 10 */
printf("Empty: %d\n", isEmpty(&s)); /* 1 (true) */
return 0;
}
- •top = -1 means empty stack
- •All operations (push, pop, peek) are O(1)
- •Array-based stack has fixed capacity -- must check for overflow
- •LIFO: last element pushed is the first one popped
- •Cache-friendly due to contiguous memory
- •Using sentinel value -1 for error on pop is ambiguous if -1 is a valid data value
- •Stack overflow (top == MAX-1) silently dropping data if not handled
- •Pre-increment vs post-increment on top: s->arr[++s->top] = val (push) vs s->arr[s->top--] (pop)
- •Fixed size means you must know the maximum capacity in advance