Lesson 1
Stacks in C#
Introduction

Greetings, Space Explorer! Today, we're drawing back the curtains on Stacks in C#, a crucial data structure. A stack is like a pile of dishes: you add a dish to the top (Last In) and take it from the top (First Out). This Last-In, First-Out (LIFO) principle exemplifies the stack. C# executes stacks effortlessly using the Stack class from the System.Collections.Generic namespace. This lesson will illuminate the stack data structure, its operations, and its applications in C#. Are you ready to start?

Utilizing Stacks in C#

To create a stack, C# employs a built-in data structure known as a Stack. For the push operation, we use Push(), which adds an element to the stack's end. For the pop operation, there's the Pop() function that removes the last element, simulating the removal of the 'top' element in a stack. Here's how it looks:

C#
1using System; 2using System.Collections.Generic; 3 4public class StackExample 5{ 6 public static void Main(string[] args) 7 { 8 Stack<string> stack = new Stack<string>(); // A new empty stack 9 10 // Push operations 11 stack.Push("John"); 12 stack.Push("Mary"); 13 stack.Push("Steve"); 14 15 stack.Pop(); // Pop operation removes 'Steve' 16 Console.WriteLine(string.Join(" -> ", stack)); // Outputs: John -> Mary 17 } 18}

In the example provided, we push John, Mary, and Steve into the stack and then pop Steve from the stack.

Advanced Stack Operations

Stack operations go beyond merely Push and Pop. For example, to verify if a stack is empty, we can check if the Count property is 0. If it is, that means the stack is empty. To peek at the top element of the stack without popping it, we use the Peek() method.

Here's an example:

C#
1using System; 2using System.Collections.Generic; 3 4public class StackOperations 5{ 6 public static void Main(string[] args) 7 { 8 Stack<string> stack = new Stack<string>(); 9 stack.Push("Steve"); 10 stack.Push("Sam"); 11 12 Console.WriteLine(stack.Peek()); // Outputs: 'Sam' 13 14 Console.WriteLine(stack.Count == 0); // Outputs: False 15 stack.Pop(); // Remove 'Sam' 16 stack.Pop(); // Remove 'Steve' 17 Console.WriteLine(stack.Count == 0); // Outputs: True 18 } 19}

In this example, Sam is added (pushed), and then the topmost stack element, which is Sam, is peeked at.

Practical Stack Applications: Reversing a String

Practical applications of stacks in C# are plentiful. Here is one of them — reversing a string.

We will push all characters into a stack and then pop them out to get a reversed string!

C#
1using System; 2using System.Collections.Generic; 3using System.Text; 4 5public class ReverseString 6{ 7 public static string Reverse(string input) 8 { 9 Stack<char> stack = new Stack<char>(); 10 11 foreach (char c in input) 12 { 13 stack.Push(c); 14 } 15 16 StringBuilder reversedString = new StringBuilder(); 17 while (stack.Count > 0) 18 { 19 reversedString.Append(stack.Pop()); 20 } 21 22 return reversedString.ToString(); 23 } 24 25 public static void Main(string[] args) 26 { 27 Console.WriteLine(Reverse("HELLO")); // Outputs: OLLEH 28 } 29}
Practical Stack Applications: Checking Balance of Parentheses

A stack can be utilized to verify if parentheses in an expression are well-matched, i.e., every bracket has a corresponding pair. For example, parentheses in the string "()[{}]" are well-matched, while in strings "([]()", ")()[]{}", "([)]", and "[{})" they are not.

Let's break down the solution into simple steps:

We start by creating a Dictionary that maps each closing bracket to its corresponding opening bracket and an empty stack. Then, we iterate over each character paren in the string parenString:

  • If paren is an opening bracket, it gets appended to the stack.
  • If paren is a closing bracket and the top element in the stack is the corresponding opening bracket, we remove the top element from the stack.
  • If neither of the above conditions is met, we return false.

Finally, if the stack is empty (all opening brackets had matching closing brackets), we return true. If there are some unmatched opening brackets left, we return false.

C#
1using System; 2using System.Collections.Generic; 3 4public class ParenthesesBalance 5{ 6 public static bool IsParenBalanced(string parenString) 7 { 8 Stack<char> stack = new Stack<char>(); 9 Dictionary<char, char> openingParen = new Dictionary<char, char> 10 { 11 { ')', '(' }, 12 { ']', '[' }, 13 { '}', '{' } 14 }; 15 16 foreach (char paren in parenString) 17 { 18 if (openingParen.ContainsValue(paren)) 19 { 20 // We met an opening parenthesis, just putting it on the stack 21 stack.Push(paren); 22 } 23 else if (openingParen.ContainsKey(paren)) 24 { 25 // We met a closing parenthesis 26 if (stack.Count == 0 || stack.Pop() != openingParen[paren]) 27 { 28 return false; 29 } 30 } 31 } 32 33 return stack.Count == 0; 34 } 35 36 public static void Main(string[] args) 37 { 38 Console.WriteLine(IsParenBalanced("(())")); // Outputs: True 39 Console.WriteLine(IsParenBalanced("({[)}")); // Outputs: False 40 } 41}
Lesson Summary

Kudos to you! Covering the stack data structure, its operations, and their applications in C# is a commendable feat. Next up, you'll encounter practice exercises that will solidify your newly acquired knowledge. Dive into them and master Stacks in C#!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.