<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. C#
  3. Working with data
All lessons in this course

Lesson 32 of 60 12 minIntermediate

HashSet, Queue and Stack

Three specialised collections: unique items with fast lookups, first-in-first-out processing, and last-in-first-out undo history.

List and Dictionary cover most needs. Three more collections solve specific problems so well that every developer should know them.

Interactive

Stack, Queue and HashSet

top ↓ (last in, first out)
Move column
Add bolt
Draw beam
var undo = new Stack<string>();Like a pile of plates: you only ever touch the top one.

HashSet<T>: unique items

HashSet.cs
var used = new HashSet<string> { "IPE200", "HEA200" };Console.WriteLine(used.Add("IPE200"));   // False: already thereConsole.WriteLine(used.Add("IPE300"));   // TrueConsole.WriteLine(used.Contains("HEA200"));Console.WriteLine(used.Count); // remove duplicates from any list in one linevar unique = new HashSet<int>(new[] { 3, 1, 3, 2, 1 });Console.WriteLine(string.Join(" ", unique));
Output
False
True
True
3
3 1 2

Sets also do maths: a.UnionWith(b) (everything in either), a.IntersectWith(b) (only in both), a.ExceptWith(b) (in a but not b). Great for “which profiles are in model A but not in model B?”.

Queue<T>: first in, first out

Queue.cs
var jobs = new Queue<string>();jobs.Enqueue("Export IFC");jobs.Enqueue("Generate drawings");jobs.Enqueue("Send report"); while (jobs.Count > 0){    string job = jobs.Dequeue();          // oldest first    Console.WriteLine($"Running: {job}");}
Output
Running: Export IFC
Running: Generate drawings
Running: Send report

Use a queue whenever work must be handled in arrival order: print jobs, messages, requests, and the breadth-first search algorithm you will meet in the DSA course.

Stack<T>: last in, first out

Undo.cs
var undo = new Stack<string>();undo.Push("Draw beam B1");undo.Push("Add bolt group");undo.Push("Move column C3"); Console.WriteLine($"Undo: {undo.Pop()}");     // most recent firstConsole.WriteLine($"Undo: {undo.Pop()}");Console.WriteLine($"Next to undo: {undo.Peek()}");
Output
Undo: Move column C3
Undo: Add bolt group
Next to undo: Draw beam B1

Stacks fit anything that must be reversed or nested: undo/redo, the browser Back button, checking matching brackets, and the call stack itself.

Safe versions

Try.cs
if (undo.TryPop(out string? action)) Console.WriteLine(action);if (jobs.TryDequeue(out string? next)) Console.WriteLine(next);

Pop, Peek and Dequeue throw InvalidOperationException when the collection is empty; the Try versions return false instead.

Collection cheat sheet

CollectionOrderDuplicatesBest at
List<T>insertion order, by indexyesgeneral ordered data
Dictionary<K,V>not guaranteedunique keyslookup by key
HashSet<T>not guaranteednomembership tests, de-duplication
Queue<T>FIFOyesprocess in arrival order
Stack<T>LIFOyesundo, nesting, backtracking
SortedDictionary<K,V>sorted by keyunique keysordered lookups
Quick check

You push 1, 2, 3 onto a Stack and then Pop once. What comes out?

Quick check

Which collection automatically ignores duplicates?

Practice

Use a Stack<char> to check whether the brackets in a string are balanced, e.g. "(a[b]{c})" is balanced and "(a[b)]" is not.

Show a hint

Push every opening bracket. For a closing bracket, the stack must not be empty and its top must be the matching opener; pop it. At the end the stack must be empty.

Show the solution
Solution.cs
static bool Balanced(string s){    var stack = new Stack<char>();    foreach (char c in s)    {        if (c is '(' or '[' or '{') stack.Push(c);        else if (c is ')' or ']' or '}')        {            if (stack.Count == 0) return false;            char open = stack.Pop();            if ((c == ')' && open != '(') || (c == ']' && open != '[') || (c == '}' && open != '{'))                return false;        }    }    return stack.Count == 0;} Console.WriteLine(Balanced("(a[b]{c})"));Console.WriteLine(Balanced("(a[b)]"));
Output
True
False

Remember

  • HashSet<T>: unique items, O(1) Contains, set operations.
  • Queue<T>: FIFO with Enqueue/Dequeue.
  • Stack<T>: LIFO with Push/Pop/Peek.
  • Use TryPop/TryDequeue to avoid exceptions on empty collections.
0 of 60 lessons completed