Linear Data Structures

Stack &
Queue

Two fundamental linear data structures that control how we add and remove elements. Master LIFO and FIFO principles through interactive visualization.

Stack

Last In, First Out. Like a pile of plates. Operations happen only at the top.

LIFO O(1) ops

Queue

First In, First Out. Like a line at a store. Fair processing order.

FIFO O(1) ops
LIFO Structure

Stack

A stack is a linear data structure that follows the Last In, First Out (LIFO) principle. The last element added is the first one to be removed. Think of it as a stack of books or plates.

1

Push Operation

Add an element to the top of the stack. O(1) time complexity.

2

Pop Operation

Remove the top element from the stack. O(1) time complexity.

3

Peek/Top

View the top element without removing it. O(1) time complexity.

JavaScript Implementation
class Stack {
    constructor() {
        this.items = [];
    }
    
    // Add to top - O(1)
    push(element) {
        this.items.push(element);
    }
    
    // Remove from top - O(1)
    pop() {
        if (this.isEmpty()) return null;
        return this.items.pop();
    }
    
    // View top - O(1)
    peek() {
        return this.items[this.items.length - 1];
    }
    
    isEmpty() {
        return this.items.length === 0;
    }
}

Interactive Stack

Live Demo
TOP
Stack is empty. Push an element to begin.
Size: 0 Max: 8
📚
Book Stack
Remove top book first
Undo Action
Reverse operations
🌐
Browser History
Back button
🧮
Call Stack
Function calls

Interactive Queue

Live Demo
FRONT
REAR
Queue is empty. Enqueue an element to begin.
Size: 0 Max: 8
🎫
Ticket Line
First come first served
🖨️
Print Spooler
Job scheduling
💬
Message Queue
Async processing
🔄
CPU Scheduling
Process management
FIFO Structure

Queue

A queue is a linear data structure that follows the First In, First Out (FIFO) principle. Elements are added at the rear and removed from the front. Like a line of people waiting for a service.

1

Enqueue Operation

Add an element to the rear (end) of the queue. O(1) time complexity.

2

Dequeue Operation

Remove an element from the front of the queue. O(1) time complexity.

3

Front/Rear Peek

View the front or rear element without removing. O(1) time complexity.

JavaScript Implementation
class Queue {
    constructor() {
        this.items = [];
        this.front = 0;
        this.rear = 0;
    }
    
    // Add to rear - O(1)
    enqueue(element) {
        this.items[this.rear] = element;
        this.rear++;
    }
    
    // Remove from front - O(1)
    dequeue() {
        if (this.isEmpty()) return null;
        const item = this.items[this.front];
        this.front++;
        return item;
    }
    
    // View front - O(1)
    peek() {
        return this.items[this.front];
    }
    
    isEmpty() {
        return this.front === this.rear;
    }
}

Types of Queues

Circular Queue
Last position connects to first
O(1)
Priority Queue
Elements served by priority
O(log n)
Deque
Insert/delete at both ends
O(1)

Stack vs Queue

Understanding the key differences helps choose the right structure for your algorithm.

Aspect Stack Queue
Principle LIFO (Last In, First Out) FIFO (First In, First Out)
Insertion Push (Top) Enqueue (Rear)
Deletion Pop (Top) Dequeue (Front)
Access Point One end (Top) Both ends (Front & Rear)
Time Complexity O(1) for all ops O(1) for all ops
Use Case Undo, Recursion, Parsing Scheduling, BFS, Buffering

Stack Analogy

1st
2nd
3rd ← Out
Last item added is the first to leave

Queue Analogy

1st → Out
2nd
3rd
First item added is the first to leave

Implementation Details

Choose the right implementation based on your constraints.

Array Implementation

Simple and cache-friendly

Pros: Memory efficient, better cache locality, simple implementation

Cons: Fixed size (unless dynamic), shifting elements in queue is O(n)

// Stack with Array
class Stack {
    constructor(capacity) {
        this.items = new Array(capacity);
        this.top = -1;
        this.capacity = capacity;
    }
    
    push(item) {
        if (this.top >= this.capacity - 1) {
            throw new Error("Stack Overflow");
        }
        this.items[++this.top] = item;
    }
    
    pop() {
        if (this.top < 0) return null;
        return this.items[this.top--];
    }
}

Linked List Implementation

Dynamic size, flexible memory

Pros: Dynamic size, no memory waste, O(1) queue operations

Cons: Extra memory for pointers, poor cache locality

// Queue with Linked List
class Node {
    constructor(data) {
        this.data = data;
        this.next = null;
    }
}

class Queue {
    constructor() {
        this.front = null;
        this.rear = null;
        this.size = 0;
    }
    
    enqueue(data) {
        const newNode = new Node(data);
        if (!this.rear) {
            this.front = this.rear = newNode;
        } else {
            this.rear.next = newNode;
            this.rear = newNode;
        }
        this.size++;
    }
}

Ready to Practice?

Test your understanding with classic stack and queue problems.