Data Structures — Stack

Henrique Siebert Domareski
5 min readApr 22, 2024

--

A Stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. This means that the last item added to the stack will be the first item to leave the stack. In this article, I present how to use this data structure in .NET.

For demonstration purposes, I created a console application using .NET. The complete code can be found on my GitHub.

The Stack data structure provides a series of methods that you can use to work with it. These are the main methods:

  • Push: this method inserts elements to the top of the stack.
  • Pop: this method removes and returns the element at the top of the stack.
  • Peek: this method returns the top element at the top of the stack (without removing it).
  • Count: this method gets the number of elements contained in the stack.
  • Contains: this method returns whether an element is in the stack.

In the image below you can see what happens when the Pushand Pop operations are executed:

  • The Push operation added the element 3 at the top of the stack.
  • The Peek operation returned the top element of the stack (element 3).
  • The Pop operation removed the top element of the stack (element 3).

Creating a Stack

To create a Stack in C#, you can declare it by using the generic class Stack<T>, where T is the type of elements that will be stored in the stack. For example, below I’m creating a Stack of string elements:

Stack<string> stackDemo = new Stack<string>();

// or

var stackDemo = new Stack<int>();

Adding elements to the Stack

In the code below I’m adding three elements to the stackDemo:

stackDemo.Push("Melon");
stackDemo.Push("Banana");
stackDemo.Push("Kiwi");

For each Push operation, the element will be added to the top of the stack:

So after adding these three elements, the “1- Melon” (the first element to be added) is at the bottom of the stack, and the “3- Kiwi” (the last element to be added) is at the top of the stack

When printing the values of this stack, this is the output:

Kiwi
Banana
Melon

Removing the top element from the Stack

The Pop operation can be used to remove the top element from the stack. For example:

stackDemo.Pop();

When executing the Pop operation, the last element that was added to the stack (“Kiwi) will be removed:

When printing the elements of the stack after executing the Pop method, this is the output:

Banana
Melon

Getting the top element from the Stack

To retrieve the top element from the Stack, you can use the Peek method:

string topItem = stackDemo.Peek();

Now when printing the topItem, this is the output:

Banana

Contains operation

To check if an element exists in the Stack, you can use the Contains method, and pass as a parameter the value that you want to search:

var containsBanana = stackDemo.Contains("Banana");
var containsApple = stackDemo.Contains("Apple");

When printing containsBanana and containsApple, this is the output:

containsBanana: True
containsApple: False

Retrieving the number of elements in a Stack

To get the amount of elements that exist in a Stack, or to check if the Stack is empty or not, you can use the Count method:

var numberOfElements = stackDemo.Count;

When printing the numberOfElements, the output is:

numberOfElements: 2

Useful cases for using a Stack

The Stack data structure is useful for scenarios such as:

  • Undo/redo operations: think of a text editor where you can undo and redo actions. Using a stack is an efficient way to manage the history of operations, allowing users to revert changes or reapply them.
  • Browser History Navigation: Browsing through web pages involves moving backwards and forward. Stacks can facilitate this navigation by maintaining a history of visited pages.
  • Recursion: Recursion is a programming technique where a function calls itself to solve a problem by breaking it down into smaller, similar subproblems. Each recursive call creates a new activation record on the call stack. The stack’s Last-In-First-Out (LIFO) property manages the recursive function calls, ensuring proper memory management.
  • Calling Functions (Call Stack): Function calls use the call stack. When a function is called, its context, including parameters and variables, is pushed onto the stack. As functions finish, they are popped off, allowing the program to resume execution from the caller. This LIFO process mirrors the behaviour of a stack.
  • Expression Evaluation and Parsing: Stack helps convert infix expressions to postfix or prefix notation (Reverse Polish Notation or Polish Notation), ensuring proper evaluation by following operator precedence rules.
  • Depth-First Search (DFS): DFS is a graph traversal algorithm that explores each branch as far as possible before backtracking. Stacks are commonly used for iterative DFS implementation, systematically managing nodes to ensure traversal of the graph’s vertices and edges.
  • Backtracking Algorithms: Applications involving backtracking, such as file directory traversal or maze-solving algorithms, rely on stacks to track and manage potential solutions.

Conclusion

The Stack data structure offers a simple but powerful mechanism for managing data in a LIFO manner. Stacks can be useful in a range of scenarios, including managing undo/redo operations, navigating browser history, handling recursion, managing function calls (call stack), implementing graph traversal algorithms, and converting infix expressions to postfix or prefix notation.

This is the link for the project in GitHub: https://github.com/henriquesd/stackdemo

If you like this demo, I kindly ask you to give a ⭐️ in the repository.

Thanks for reading!

--

--