C# Stack and Queue
Stack and Queue are two specialized collection types that control the order in which items are added and removed. Each follows a strict rule — and that rule makes them powerful for specific programming problems.
Stack — Last In, First Out (LIFO)
A stack works like a stack of plates. You place a plate on top, and you take the top plate first. The last item you added is the first one you remove.
┌──────────────────────────────────────────────────────────────┐
│ STACK — LIFO │
├──────────────────────────────────────────────────────────────┤
│ │
│ Push "A": [A] │
│ Push "B": [A][B] │
│ Push "C": [A][B][C] ← top │
│ │
│ Pop(): [A][B] returns "C" │
│ Pop(): [A] returns "B" │
│ Pop(): [] returns "A" │
│ │
│ Last in ("C") → First out ("C") │
└──────────────────────────────────────────────────────────────┘
Creating and Using a Stack
using System;
using System.Collections.Generic;
Stack<string> stack = new Stack<string>();
stack.Push("Page 1"); // add to top
stack.Push("Page 2");
stack.Push("Page 3"); // top of stack
Console.WriteLine(stack.Peek()); // "Page 3" — look at top (no remove)
Console.WriteLine(stack.Pop()); // "Page 3" — remove and return top
Console.WriteLine(stack.Pop()); // "Page 2"
Console.WriteLine(stack.Count); // 1
Stack Methods
┌───────────────┬─────────────────────────────────────────────┐ │ Method │ What It Does │ ├───────────────┼─────────────────────────────────────────────┤ │ Push(item) │ Add item to the top │ │ Pop() │ Remove and return item from top │ │ Peek() │ View top item without removing │ │ Contains(item)│ Check if item exists │ │ Count │ Number of items │ │ Clear() │ Remove all items │ └───────────────┴─────────────────────────────────────────────┘
Real-World Stack Use: Browser Back Button
Stack<string> history = new Stack<string>();
history.Push("https://google.com");
history.Push("https://example.com");
history.Push("https://blog.com");
// User clicks Back:
string currentPage = history.Pop();
Console.WriteLine("Went back to: " + history.Peek());
// Went back to: https://example.com
Undo Feature Diagram
┌────────────────────────────────────────────────────────────┐ │ UNDO WITH STACK │ ├────────────────────────────────────────────────────────────┤ │ │ │ User types "H": [H] │ │ User types "e": [H][e] │ │ User types "l": [H][e][l] │ │ User types "p": [H][e][l][p] │ │ │ │ Ctrl+Z (Undo): [H][e][l] → removed "p" │ │ Ctrl+Z (Undo): [H][e] → removed "l" │ │ │ └────────────────────────────────────────────────────────────┘
Queue — First In, First Out (FIFO)
A queue works like a line at a ticket counter. The first person in line gets served first. Items enter from the back and leave from the front.
┌──────────────────────────────────────────────────────────────┐
│ QUEUE — FIFO │
├──────────────────────────────────────────────────────────────┤
│ │
│ Enqueue "A": [A] │
│ Enqueue "B": [A][B] │
│ Enqueue "C": [A][B][C] │
│ ↑ ↑ │
│ Front Back │
│ │
│ Dequeue(): [B][C] returns "A" (front) │
│ Dequeue(): [C] returns "B" │
│ Dequeue(): [] returns "C" │
│ │
│ First in ("A") → First out ("A") │
└──────────────────────────────────────────────────────────────┘
Creating and Using a Queue
Queue<string> queue = new Queue<string>();
queue.Enqueue("Task 1"); // add to back
queue.Enqueue("Task 2");
queue.Enqueue("Task 3");
Console.WriteLine(queue.Peek()); // "Task 1" — view front (no remove)
Console.WriteLine(queue.Dequeue()); // "Task 1" — remove and return front
Console.WriteLine(queue.Dequeue()); // "Task 2"
Console.WriteLine(queue.Count); // 1
Queue Methods
┌───────────────┬─────────────────────────────────────────────┐ │ Method │ What It Does │ ├───────────────┼─────────────────────────────────────────────┤ │ Enqueue(item) │ Add item to the back │ │ Dequeue() │ Remove and return item from front │ │ Peek() │ View front item without removing │ │ Contains(item)│ Check if item exists │ │ Count │ Number of items │ │ Clear() │ Remove all items │ └───────────────┴─────────────────────────────────────────────┘
Real-World Queue Use: Print Spooler
Queue<string> printQueue = new Queue<string>();
printQueue.Enqueue("Invoice.pdf");
printQueue.Enqueue("Report.docx");
printQueue.Enqueue("Photo.jpg");
Console.WriteLine("Printing documents in order:");
while (printQueue.Count > 0)
{
string doc = printQueue.Dequeue();
Console.WriteLine("Printing: " + doc);
}
// Output:
// Printing: Invoice.pdf
// Printing: Report.docx
// Printing: Photo.jpg
Stack vs Queue Side-by-Side
┌────────────────────────────┬────────────────────────────────┐ │ Stack (LIFO) │ Queue (FIFO) │ ├────────────────────────────┼────────────────────────────────┤ │ Last in = First out │ First in = First out │ ├────────────────────────────┼────────────────────────────────┤ │ Push() to add │ Enqueue() to add │ │ Pop() to remove │ Dequeue() to remove │ │ Peek() to view top │ Peek() to view front │ ├────────────────────────────┼────────────────────────────────┤ │ Stack of plates │ Queue at a counter │ ├────────────────────────────┼────────────────────────────────┤ │ Undo/redo, back navigation │ Print queues, task processing │ │ Expression evaluation │ Message queues, breadth-first │ └────────────────────────────┴────────────────────────────────┘
Looping Through Stack and Queue
Stack<int> s = new Stack<int>();
s.Push(1); s.Push(2); s.Push(3);
// foreach on Stack iterates from top to bottom:
foreach (int item in s)
{
Console.Write(item + " "); // 3 2 1
}
Queue<int> q = new Queue<int>();
q.Enqueue(10); q.Enqueue(20); q.Enqueue(30);
// foreach on Queue iterates from front to back:
foreach (int item in q)
{
Console.Write(item + " "); // 10 20 30
}
Converting to Array
Stack<string> stack = new Stack<string>();
stack.Push("A"); stack.Push("B"); stack.Push("C");
string[] arr = stack.ToArray(); // ["C", "B", "A"] — top first
Quick Summary
┌─────────────────────────────────────────────────────────────┐ │ Stack → LIFO → Use when order = reverse of arrival │ │ Queue → FIFO → Use when order = order of arrival │ │ │ │ Both in: System.Collections.Generic │ │ Both support: Count, Contains(), Clear(), ToArray() │ └─────────────────────────────────────────────────────────────┘
Stack and Queue solve ordering problems elegantly. Any time your data has a clear "in order" or "reverse order" rule for processing, these two collections provide a clean and efficient solution without any extra logic.
