Stacks and Queues in C#

Welcome to an exciting exploration of two fundamental data structures: Stacks and Queues! Remember, data structures store and organize data in a manner that is structured and efficient. Stacks and Queues are akin to stacking plates and standing in line, respectively. Intriguing, isn't it? Let's dive in!

Stacks: Last In, First Out (LIFO)

A Stack adheres to the "Last In, First Out" or LIFO principle. It's like a pile of plates where the last plate added is the first one to be removed. C# uses the Stack<T> class to create a stack, with Push used for insert (push), and Pop used for remove (pop, return the element that has been removed).

Let's explore this using a pile of plates.

using System;
using System.Collections.Generic;

class StackOfPlates {
    private Stack<string> stack;

    public StackOfPlates() {
        stack = new Stack<string>();
    }

    // Insert a plate at the top of the stack
    public void AddPlate(string plate) {
        stack.Push(plate);
    }

    // Remove the top plate from the stack
    public string RemovePlate() {
        if (stack.Count == 0) {
            return "No plates left to remove!";
        }
        return stack.Pop();
    }
}

// Create a stack of plates
class Program {
    static void Main() {
        StackOfPlates plates = new StackOfPlates();
        plates.AddPlate("Plate");  // Pushing a plate
        plates.AddPlate("Another Plate");  // Pushing another plate
        // Let's remove a plate; it should be the last one we added.
        Console.WriteLine("Removed: " + plates.RemovePlate());  // Outputs: Removed: Another Plate
    }
}

The last plate added was removed first, demonstrating the LIFO property of a stack.

Queues: First In, First Out (FIFO)

A Queue represents the "First In, First Out" or FIFO principle, much like waiting in line at the grocery store. In C#, we can use the Queue<T> class to achieve this behavior, using Enqueue for enqueue (insert at the end) and Dequeue for dequeue (remove from the front, return the element that has been removed).

Let's examine this through a queue of people.

using System;
using System.Collections.Generic;

class QueueOfPeople {
    private Queue<string> queue;

    public QueueOfPeople() {
        queue = new Queue<string>();
    }

    // Add a person to the end of the queue
    public void EnqueuePerson(string person) {
        queue.Enqueue(person);
    }

    // Remove the first person from the queue (who has been waiting the longest)
    public string DequeuePerson() {
        if (queue.Count == 0) {
            return "No people left to dequeue!";
        }
        return queue.Dequeue();
    }
}

// Create a queue of people
class Program {
    static void Main() {
        QueueOfPeople people = new QueueOfPeople();
        people.EnqueuePerson("Person 1");  // Person 1 enters the queue
        people.EnqueuePerson("Person 2");  // Person 2 arrives after Person 1
        // Who's next in line? It must be Person 1!
        Console.WriteLine("Removed: " + people.DequeuePerson());  // Outputs: Removed: Person 1
    }
}

Here, Person 1, the first to join the queue, left before Person 2, demonstrating the FIFO property of a queue.

Mastering Stack and Queue Operations with a Class

Stacks handle ordered data efficiently, much like your web browser's history. Queues, on the other hand, are optimal when the order of arrival is essential, such as in a store queue.

Let's depict the two structures in a text editor that features an Undo mechanism (a Stack) and a Print Queue.

using System;
using System.Collections.Generic;

class TextEditor {
    private Stack<string> stack;
    private Queue<string> queue;

    public TextEditor() {
        stack = new Stack<string>();
        queue = new Queue<string>();
    }

    // Make a change (e.g., edit text, insert image, change font)
    public void MakeChange(string action) {
        stack.Push(action);  // Add to the stack of actions
    }

    // Undo the most recent change
    public string UndoChange() {
        if (stack.Count == 0) {
            return "No changes to undo!";
        }
        return stack.Pop();  // Remove the last action from the stack
    }

    // Add a document to the queue for printing
    public void AddToPrint(string doc) {
        queue.Enqueue(doc);
    }

    // Print the document that has been waiting the longest
    public string PrintDoc() {
        if (queue.Count == 0) {
            return "No documents in print queue!";
        }
        return queue.Dequeue();  // Remove the first document from the queue
    }
}

// Use our text editor!
class Program {
    static void Main() {
        TextEditor editor = new TextEditor();
        editor.MakeChange("Changed font size");  // Make a change
        editor.MakeChange("Inserted image");  // Make another change
        // Let's undo a change. It should be the last change we made.
        Console.WriteLine("Undo: " + editor.UndoChange());  // Undo: Inserted image

        editor.AddToPrint("Proposal.docx");  // Queue a document for printing
        editor.AddToPrint("Report.xlsx");  // Queue another document
        // Let's print a document. It should be the document that has been waiting the longest.
        Console.WriteLine("Print: " + editor.PrintDoc());  // Print: Proposal.docx
    }
}

This code reintroduces the concepts of a Stack (Undo feature) and Queue (Print queue) in the context of a real-life scenario.

Lesson Summary

Great work! You have examined the mechanics of Stacks and Queues, both integral data structures. Remember to practice what you've learned. Happy coding!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal