C# Queues
Introduction
A Queue is a special type of collection that stores elements in a First-In, First-Out (FIFO) order. This means that the first element added to the queue is the first one to be removed. Think of it like waiting in line at a store - the person who arrives first gets served first.
Queues are part of the .NET Collections namespace and are commonly used in scenarios where you need to process items in the exact order they were received, such as:
- Print job scheduling
- Message processing systems
- Request handling in web servers
- Breadth-first search algorithms
- Task scheduling
In this tutorial, we'll explore how to create and use the Queue<T>
class in C#, understand its key methods, and see practical applications.
Creating a Queue in C#
To work with queues in C#, you need to include the appropriate namespace:
using System.Collections.Generic;
Basic Queue Creation
You can create a queue in several ways:
// Creating an empty queue of integers
Queue<int> numbers = new Queue<int>();
// Creating a queue with initial capacity
Queue<string> names = new Queue<string>(capacity: 10);
// Creating a queue from an existing collection
string[] people = { "Alice", "Bob", "Charlie" };
Queue<string> peopleQueue = new Queue<string>(people);
Key Queue Operations
Adding Items to a Queue (Enqueue)
To add an item to a queue, use the Enqueue
method:
Queue<string> customers = new Queue<string>();
customers.Enqueue("Alice");
customers.Enqueue("Bob");
customers.Enqueue("Charlie");
Console.WriteLine($"Number of customers waiting: {customers.Count}");
// Output: Number of customers waiting: 3
Removing Items from a Queue (Dequeue)
To remove and get the item at the front of the queue, use the Dequeue
method:
Queue<string> customers = new Queue<string>();
customers.Enqueue("Alice");
customers.Enqueue("Bob");
customers.Enqueue("Charlie");
string firstCustomer = customers.Dequeue();
Console.WriteLine($"Now serving: {firstCustomer}");
// Output: Now serving: Alice
Console.WriteLine($"Number of customers waiting: {customers.Count}");
// Output: Number of customers waiting: 2
Peeking at Items (Peek)
To view the first item without removing it, use the Peek
method:
Queue<string> customers = new Queue<string>();
customers.Enqueue("Alice");
customers.Enqueue("Bob");
string nextCustomer = customers.Peek();
Console.WriteLine($"Next customer: {nextCustomer}");
// Output: Next customer: Alice
// The queue still contains the same elements
Console.WriteLine($"Number of customers waiting: {customers.Count}");
// Output: Number of customers waiting: 2
Checking if Items Exist (Contains)
To check if an item exists in the queue:
Queue<string> customers = new Queue<string>();
customers.Enqueue("Alice");
customers.Enqueue("Bob");
bool isBobWaiting = customers.Contains("Bob");
Console.WriteLine($"Is Bob in the queue? {isBobWaiting}");
// Output: Is Bob in the queue? True
bool isCharlieWaiting = customers.Contains("Charlie");
Console.WriteLine($"Is Charlie in the queue? {isCharlieWaiting}");
// Output: Is Charlie in the queue? False
Clearing a Queue
To remove all elements from a queue:
Queue<string> customers = new Queue<string>();
customers.Enqueue("Alice");
customers.Enqueue("Bob");
Console.WriteLine($"Customers waiting: {customers.Count}");
// Output: Customers waiting: 2
customers.Clear();
Console.WriteLine($"Customers waiting after clearing: {customers.Count}");
// Output: Customers waiting after clearing: 0
Iterating Through a Queue
You can iterate through a queue without modifying it using a foreach
loop:
Queue<string> customers = new Queue<string>();
customers.Enqueue("Alice");
customers.Enqueue("Bob");
customers.Enqueue("Charlie");
Console.WriteLine("Customers in queue:");
foreach (string customer in customers)
{
Console.WriteLine(customer);
}
// Output:
// Customers in queue:
// Alice
// Bob
// Charlie
Note that iterating through a queue does not remove the elements. The queue remains unchanged.
Converting a Queue to an Array
Sometimes you might need to convert a queue to an array:
Queue<string> customers = new Queue<string>();
customers.Enqueue("Alice");
customers.Enqueue("Bob");
customers.Enqueue("Charlie");
string[] customerArray = customers.ToArray();
Console.WriteLine("Customer array contents:");
foreach (string customer in customerArray)
{
Console.WriteLine(customer);
}
// Output:
// Customer array contents:
// Alice
// Bob
// Charlie
Real-World Applications
Example 1: Print Queue Simulation
This example simulates a print queue where documents are processed in the order they were submitted:
using System;
using System.Collections.Generic;
using System.Threading;
class PrintJob
{
public string DocumentName { get; }
public int Pages { get; }
public PrintJob(string documentName, int pages)
{
DocumentName = documentName;
Pages = pages;
}
}
class PrinterSimulation
{
public static void Main()
{
Queue<PrintJob> printQueue = new Queue<PrintJob>();
// Add print jobs to queue
printQueue.Enqueue(new PrintJob("Report.pdf", 5));
printQueue.Enqueue(new PrintJob("Invoice.docx", 2));
printQueue.Enqueue(new PrintJob("Presentation.pptx", 15));
Console.WriteLine($"Number of print jobs in queue: {printQueue.Count}");
// Process print jobs
ProcessPrintJobs(printQueue);
}
private static void ProcessPrintJobs(Queue<PrintJob> queue)
{
Console.WriteLine("Starting printer...");
while (queue.Count > 0)
{
PrintJob job = queue.Dequeue();
Console.WriteLine($"Printing: {job.DocumentName} ({job.Pages} pages)");
// Simulate printing time (1 second per page)
for (int i = 1; i <= job.Pages; i++)
{
Console.WriteLine($" Printed page {i} of {job.Pages}");
Thread.Sleep(1000); // Simulate 1 second printing time
}
Console.WriteLine($"Completed: {job.DocumentName}");
Console.WriteLine($"Remaining jobs: {queue.Count}");
}
Console.WriteLine("All print jobs completed.");
}
}
// Output:
// Number of print jobs in queue: 3
// Starting printer...
// Printing: Report.pdf (5 pages)
// Printed page 1 of 5
// ...
// Printed page 5 of 5
// Completed: Report.pdf
// Remaining jobs: 2
// ...
// All print jobs completed.
Example 2: Customer Service System
This example demonstrates a simple customer service system where customers are served in the order they arrived:
using System;
using System.Collections.Generic;
class CustomerServiceSystem
{
public static void Main()
{
Queue<string> customerQueue = new Queue<string>();
bool running = true;
while (running)
{
Console.WriteLine("\n==== Customer Service System ====");
Console.WriteLine("1. Add customer to queue");
Console.WriteLine("2. Serve next customer");
Console.WriteLine("3. View all waiting customers");
Console.WriteLine("4. Check queue length");
Console.WriteLine("5. Exit");
Console.Write("Select an option: ");
string choice = Console.ReadLine();
switch (choice)
{
case "1":
Console.Write("Enter customer name: ");
string name = Console.ReadLine();
customerQueue.Enqueue(name);
Console.WriteLine($"{name} has been added to the queue.");
break;
case "2":
if (customerQueue.Count > 0)
{
string customer = customerQueue.Dequeue();
Console.WriteLine($"Now serving: {customer}");
}
else
{
Console.WriteLine("No customers in queue.");
}
break;
case "3":
if (customerQueue.Count > 0)
{
Console.WriteLine("\nCustomers waiting:");
int position = 1;
foreach (string customer in customerQueue)
{
Console.WriteLine($"{position}: {customer}");
position++;
}
}
else
{
Console.WriteLine("No customers in queue.");
}
break;
case "4":
Console.WriteLine($"Current queue length: {customerQueue.Count} customers");
break;
case "5":
running = false;
break;
default:
Console.WriteLine("Invalid option. Please try again.");
break;
}
}
Console.WriteLine("Program ended.");
}
}
// Sample interaction:
// ==== Customer Service System ====
// 1. Add customer to queue
// 2. Serve next customer
// 3. View all waiting customers
// 4. Check queue length
// 5. Exit
// Select an option: 1
// Enter customer name: John
// John has been added to the queue.
// ...
Performance Considerations
The Queue<T>
class provides efficient operations for its intended purpose:
- Enqueue and Dequeue operations are O(1) - constant time operations
- Contains operation is O(n) - it needs to scan through the entire queue
- Count property is O(1) - constant time
- Peek is O(1) - constant time
Queue vs. Stack vs. List
Operation | Queue | Stack | List |
---|---|---|---|
Add | Enqueue (at end) | Push (at top) | Add (at end) or Insert (at index) |
Remove | Dequeue (from front) | Pop (from top) | RemoveAt (at index) |
Access | Peek (front only) | Peek (top only) | Direct access by index |
Order | FIFO (First In, First Out) | LIFO (Last In, First Out) | Indexed access |
Choose a Queue when you need to process items in the exact order they were received.
Summary
In this tutorial, we explored C# Queues, which implement a First-In, First-Out (FIFO) data structure. We covered:
- Creating and initializing queues
- Key operations like Enqueue, Dequeue, and Peek
- Checking if elements exist in a queue
- Iterating through a queue
- Converting queues to arrays
- Real-world applications like print queues and customer service systems
Queues are essential data structures that help manage data in the order it is received, making them suitable for scenarios where processing order matters.
Practice Exercises
- Create a message processing system that adds messages to a queue and processes them one by one.
- Implement a breadth-first search algorithm for a simple graph using a queue.
- Build a playlist application where songs are played in the order they were added.
- Create a simulation of a call center where callers are placed in a queue and answered in order.
Additional Resources
- Microsoft Documentation on
Queue<T>
- C# Queue Examples on Microsoft Learn
- Data Structures: Queue Implementation in C#
Happy coding with C# Queues!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)