C Data Structures: Stacks & Queues โ€” Array vs Linked List Implementations Masterclass

โšก C (C17 / C23 Standard) ๐ŸŸข Lesson 48 ๐Ÿ“‚ Phase 18: Data Structures in C ๐Ÿ“… 2026 Comprehensive Master Edition
๐Ÿ“Œ Covered in this in-depth guide: Stack LIFO ยท Array Stack vs Linked Stack ยท Queue FIFO ยท Circular Array Queue ยท Linked List Queue ยท Deque ยท Stack-based Expression Evaluation

Welcome to Phase 18 (Chapter 48): C Data Structures โ€” Stacks & Queues, Array vs Linked List Implementations Masterclass! Stacks (LIFO) and Queues (FIFO) are the two most fundamental Abstract Data Types (ADTs) in computer science. They underpin function call management, expression parsing, task scheduling, and BFS/DFS graph traversal.

1Stack โ€” LIFO Architecture & Memory Model
Array-Based Stack (top index tracks last element): data[]: [10] [20] [30] [ ] [ ] (capacity=5) index: 0 1 2 3 4 top = 2 โ–ฒ push(40) โ†’ data[3]=40, top=3 pop() โ†’ returns data[3]=40, top=2
2Complete Stack Implementation (Array-Based)
C โ€” Generic Array Stackโ–ถ Try in Compiler
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define STACK_MAX 100

typedef struct {
    int data[STACK_MAX];
    int top;         /* Index of top element; -1 = empty */
} Stack;

void  stack_init(Stack *s)       { s->top = -1; }
bool  stack_empty(const Stack *s){ return s->top == -1; }
bool  stack_full(const Stack *s) { return s->top == STACK_MAX - 1; }

bool  stack_push(Stack *s, int v) {
    if (stack_full(s)) return false;
    s->data[++s->top] = v;
    return true;
}

bool stack_pop(Stack *s, int *out) {
    if (stack_empty(s)) return false;
    *out = s->data[s->top--];
    return true;
}

int stack_peek(const Stack *s) { return s->data[s->top]; }

/* Application: Check balanced brackets */
bool is_balanced(const char *expr) {
    Stack s; stack_init(&s);
    for (int i = 0; expr[i]; i++) {
        if (expr[i]=='('||expr[i]=='['||expr[i]=='{') {
            stack_push(&s, expr[i]);
        } else if (expr[i]==')'||expr[i]==']'||expr[i]=='}') {
            if (stack_empty(&s)) return false;
            int top; stack_pop(&s, &top);
            if ((expr[i]==')' && top!='(')||
                (expr[i]==']' && top!='[')||
                (expr[i]=='}' && top!='{')) return false;
        }
    }
    return stack_empty(&s);
}

int main(void) {
    printf("is_balanced(\"[(){()}]\") = %s\n", is_balanced("[(){()}]") ? "YES" : "NO");
    printf("is_balanced(\"[(])\")     = %s\n", is_balanced("[(])") ? "YES" : "NO");
    return 0;
}
3Queue โ€” FIFO with Circular Array

A naive array queue wastes space as front advances. A circular array queue wraps indices using modulo arithmetic, achieving O(1) enqueue and dequeue with no wasted space:

Circular Queue Index Math:

โ€ข rear = (rear + 1) % CAPACITY โ€” Advance rear pointer (wraps around).

โ€ข front = (front + 1) % CAPACITY โ€” Advance front pointer.

โ€ข Full condition: (rear + 1) % CAPACITY == front

โ€ข Empty condition: front == rear

4Technical FAQs

Q1: What is a Deque (Double-Ended Queue)?

A Deque supports push/pop at BOTH front and back in O(1). Implemented with a doubly-linked list or circular array. Used for monotonic queue algorithms.

Q2: Why use linked list stack over array stack?

Linked list stack grows dynamically (no fixed capacity). Array stack has O(1) cache-friendly access but must pre-allocate maximum size.

Q3: What is the function call stack?

The CPU maintains a hardware stack (pointed to by SP register) where each function call pushes a frame containing local variables, return address, and saved registers.

Q4: How is a Queue used in BFS graph traversal?

Start by enqueuing the source node. Dequeue a node, process it, enqueue all unvisited neighbors. This guarantees visiting nodes in level-order (shortest-path-first).

Q5: What is a Priority Queue?

A Priority Queue dequeues elements by priority value, not FIFO order. Implemented with a binary heap (min-heap or max-heap). Used in Dijkstra's shortest path and task schedulers.