Lesson 4
Queues: Concepts and Implementation in C#
Introduction to Queues

Hello there! Today, we will unveil Queues in coding, likening them to a line in a coffee shop or a queue of print requests. Queues in computer science are First-In, First-Out (FIFO) structures. Consider this example: you're at a theme park — the first person in line for the roller coaster gets on first. Today's lesson revolves around this straightforward yet powerful concept. So, let's dive in!

Implementing a Queue in C#

Let's explore the implementation of Queues in C#. An array is ideal for implementing a Queue. Let's define the Queue:

C#
1public class Queue { 2 private int front, rear, size, capacity; 3 private int[] array; 4 5 public Queue(int capacity) { 6 this.capacity = capacity; // Set the max size 7 front = size = 0; // Initialize front and size 8 rear = capacity - 1; // Initialize rear 9 array = new int[this.capacity]; 10 } 11 12 // Will return true if the Queue is full 13 public bool IsFull() { 14 return (size == capacity); 15 } 16}

In the Queue class above, the IsFull() method checks if our queue is already at maximum capacity.

Queue Enqueue Operation

Enqueue, a fancy term, denotes adding an item to the queue — the item lines up at the rear. Here's how it plays out in our Queue class:

C#
1public void Enqueue(int item) { 2 if (IsFull()) // Check if the queue is full 3 return; 4 rear = (rear + 1) % capacity; // Move rear 5 array[rear] = item; // Add item at rear position 6 size = size + 1; // increment size 7}

rear = (rear + 1) % capacity uses the modulo operator to calculate the new position for the rear pointer, ensuring it wraps around to the start of the queue when it surpasses the maximum index, thereby maintaining a circular behavior.

Queue Dequeue Operation

Just as Enqueue adds an element to our queue, Dequeue removes it. It extracts the element at the queue's front, reducing its size. However, we encounter an underflow condition if there are no elements to remove.

C#
1public int Dequeue() { 2 if (IsEmpty()) // Check if the queue is empty 3 return int.MinValue; 4 5 int item = array[front]; // Item at front 6 front = (front + 1) % capacity; // Move front 7 size = size - 1; // decrement size 8 return item; // return removed item 9} 10 11public bool IsEmpty() { 12 return (size == 0); 13}

The Dequeue() method checks for emptiness before dispatching the item.

Complexity Analysis of Queue Operations

The time complexity of enqueue and dequeue operations remains constant: O(1). However, the space complexity varies with the size of the queue, making it O(n).

Using C#'s Queue<T> Class

While it is essential to understand the queue's inner structure, we won't implement it ourselves. Instead, we will use C#'s built-in Queue<T> class. Think of any system that needs to handle requests in a fair, first-come-first-served order. These are all excellent candidates for using a queue. Here's how you can declare, initialize, and utilize a Queue<T> using C#:

C#
1using System; 2using System.Collections.Generic; 3 4public class MainClass { 5 public static void Main(string[] args) { 6 // Create and initialize a Queue using a List 7 Queue<int> queue = new Queue<int>(); 8 9 // Add elements {0, 1, 2, 3, 4} to queue 10 for (int i = 0; i < 5; i++) 11 queue.Enqueue(i); 12 13 // Display contents of the queue. 14 Console.WriteLine("Elements of queue: " + String.Join(", ", queue)); 15 16 // To remove the head of queue. 17 int removedElement = queue.Dequeue(); 18 Console.WriteLine("Removed element: " + removedElement); 19 20 Console.WriteLine("Queue after removal: " + String.Join(", ", queue)); 21 22 // To view the head of queue 23 int head = queue.Peek(); 24 Console.WriteLine("Head of queue: " + head); 25 26 // Rest all methods of collection interface 27 int size = queue.Count; 28 Console.WriteLine("Size of queue: " + size); 29 } 30} 31 32/* Output: 33Elements of queue: 0, 1, 2, 3, 4 34Removed element: 0 35Queue after removal: 1, 2, 3, 4 36Head of queue: 1 37Size of queue: 4 38*/

In the above example, we create an instance of Queue<int> using C#. Key Queue operations include:

  • Enqueue(): Inserts the specified element into the Queue.
  • Dequeue(): Removes and returns the head of the Queue.
  • Peek(): Retrieves, but does not remove, the head of the Queue, returning null if the queue is empty.
  • Count: Returns the number of elements in the Queue.

C#'s Queue<T> class is versatile and can accommodate diverse data types.

In Summary: Queues

We've learned about the Queue, its operations, and its implementation in C#. Furthermore, these techniques are fundamental for smooth functioning in daily life. They are invaluable and versatile in various applications, from data buffering in hardware to process scheduling in operating systems.

With your newfound knowledge of the Queue data structure, it's time to level up! Next are some practice problems to enhance your understanding of these concepts. Let's dive in!

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