The Stack<T> class in C# is part of the System.Collections.Generic namespace and implements a last-in, first-out (LIFO) collection, where the last element added is the first one to be removed.
Stacks are useful when you need to manage elements in reverse order, such as processing tasks or tracking application states.
Key operations in a stack are Push (to add an item) and Pop (to remove and retrieve the most recent item).
In this tutorial, we’ll cover:
1. Creating a Stack<T>
To create a Stack<T>, include the System.Collections.Generic namespace. T is the type parameter representing the type of elements in the stack, such as int, string, or a custom class.
using System; using System.Collections.Generic; class Program { static void Main() { // Create an empty stack of integers Stack<int> numberStack = new Stack<int>(); // Create a stack of strings with initial values Stack<string> nameStack = new Stack<string>(new string[] { "Alice", "Bob", "Charlie" }); Console.WriteLine("Initial name stack:"); foreach (string name in nameStack) { Console.WriteLine(name); } } }
Output:
Initial name stack: Charlie Bob Alice
In this example:
- Stack<int> numberStack = new Stack<int>(); creates an empty stack of integers.
- Stack<string> nameStack = new Stack<string>(new string[] { “Alice”, “Bob”, “Charlie” }); initializes a stack of strings with initial values. The order of elements in the stack reflects the LIFO principle, with “Charlie” at the top.
2. Adding Elements with Push
You can add elements to a stack using the Push method. Each item added goes on top of the stack.
using System; using System.Collections.Generic; class Program { static void Main() { Stack<int> numberStack = new Stack<int>(); // Adding elements numberStack.Push(10); numberStack.Push(20); numberStack.Push(30); Console.WriteLine("Stack after pushing elements:"); foreach (int number in numberStack) { Console.WriteLine(number); } } }
Output:
Stack after pushing elements: 30 20 10
In this example:
- The Push method adds elements to the top of the stack. The elements are displayed in reverse order of insertion, with the most recent addition (30) on top.
3. Retrieving and Removing Elements with Pop
You can remove and retrieve the top element of the stack using the Pop method.
using System; using System.Collections.Generic; class Program { static void Main() { Stack<int> numberStack = new Stack<int>(new int[] { 10, 20, 30 }); // Remove and retrieve the top element int topElement = numberStack.Pop(); Console.WriteLine("Popped element: " + topElement); Console.WriteLine("Stack after popping:"); foreach (int number in numberStack) { Console.WriteLine(number); } } }
Output:
Popped element: 30 Stack after popping: 20 10
In this example:
- Pop removes the top element (30) from the stack and returns it.
- After Pop, the stack no longer contains 30, with 20 as the new top element.
Note: Attempting to Pop from an empty stack will throw an InvalidOperationException.
4. Retrieving the Top Element with Peek
The Peek method allows you to view the top element without removing it from the stack.
using System; using System.Collections.Generic; class Program { static void Main() { Stack<int> numberStack = new Stack<int>(new int[] { 10, 20, 30 }); // Retrieve the top element without removing it int topElement = numberStack.Peek(); Console.WriteLine("Top element (Peek): " + topElement); Console.WriteLine("Stack after Peek (unchanged):"); foreach (int number in numberStack) { Console.WriteLine(number); } } }
Output:
Top element (Peek): 30 Stack after Peek (unchanged): 30 20 10
In this example:
- Peek returns the top element (30) without removing it, leaving the stack unchanged.
Note: Attempting to Peek from an empty stack will throw an InvalidOperationException.
5. Checking the Number of Elements and Clearing the Stack
You can check the number of elements in a stack using Count and clear all elements using Clear.
using System; using System.Collections.Generic; class Program { static void Main() { Stack<int> numberStack = new Stack<int>(new int[] { 10, 20, 30 }); // Check the number of elements Console.WriteLine("Count: " + numberStack.Count); // Clear all elements from the stack numberStack.Clear(); Console.WriteLine("Count after clearing: " + numberStack.Count); } }
Output:
Count: 3 Count after clearing: 0
In this example:
- Count returns the number of elements in the stack.
- Clear removes all elements, resulting in an empty stack with a Count of 0.
6. Iterating Through a Stack
You can iterate through a stack using a foreach loop. The items are iterated in LIFO order, starting from the top.
using System; using System.Collections.Generic; class Program { static void Main() { Stack<string> nameStack = new Stack<string>(new string[] { "Alice", "Bob", "Charlie" }); Console.WriteLine("Iterating through the stack:"); foreach (string name in nameStack) { Console.WriteLine(name); } } }
Output:
Iterating through the stack: Charlie Bob Alice
In this example:
- The foreach loop iterates over the stack from the top element to the bottom.
7. Practical Examples of Stack<T> in Real Scenarios
Example 1: Checking for Balanced Parentheses
A common use of stacks is to check for balanced parentheses in an expression.
using System; using System.Collections.Generic; class Program { static bool IsBalanced(string expression) { Stack<char> stack = new Stack<char>(); foreach (char ch in expression) { if (ch == '(') { stack.Push(ch); } else if (ch == ')') { if (stack.Count == 0) { return false; // No matching '(' } stack.Pop(); } } return stack.Count == 0; // Balanced if stack is empty } static void Main() { string expression = "(1 + (2 * 3))"; Console.WriteLine($"Is the expression '{expression}' balanced? " + IsBalanced(expression)); } }
Output:
Is the expression '(1 + (2 * 3))' balanced? True
In this example:
- IsBalanced checks if every opening parenthesis has a corresponding closing parenthesis.
- Push adds an opening parenthesis to the stack, while Pop removes it if a closing parenthesis is found.
Example 2: Reversing a String
Stacks are useful for reversing data because of their LIFO structure.
using System; using System.Collections.Generic; class Program { static string ReverseString(string input) { Stack<char> stack = new Stack<char>(); // Push each character onto the stack foreach (char ch in input) { stack.Push(ch); } // Pop characters to build the reversed string string reversed = ""; while (stack.Count > 0) { reversed += stack.Pop(); } return reversed; } static void Main() { string input = "Hello"; Console.WriteLine($"Original string: {input}"); Console.WriteLine($"Reversed string: {ReverseString(input)}"); } }
Output:
Original string: Hello Reversed string: olleH
In this example:
- Push adds each character of the string to the stack.
- Pop retrieves the characters in reverse order, building the reversed string.
Summary
In this tutorial, we covered the Stack<T> class in C# and demonstrated its features:
- Creating a Stack<T>: Initializing stacks with or without initial values.
- Adding Elements: Using Push to add items.
- Retrieving and Removing Elements: Using Pop to remove and retrieve the top item.
- Retrieving the Top Element: Using Peek to look at the top item without removing it.
- Checking the Number of Elements and Clearing the Stack: Using Count and Clear.
- Iterating Through a Stack: Using foreach to iterate from top to bottom.
- Practical Examples: Checking for balanced parentheses and reversing a string.
The Stack<T> class is a powerful collection type in C# that simplifies working with LIFO data structures, making it ideal for a range of applications, including backtracking algorithms, expression parsing, and string manipulation.