Like Stacks, another data structure that is widely used to store data during program execution is Queues. The queues work on the FIFO (First In, First Out) principle, meaning that the first element that goes in is the first element that comes out.
You can understand its structure by considering an open container from both ends. The first thing you put into the container comes out first from the other end. For example, imagine people standing in line to pay their electricity bills. The person who came first would be the person who pays the bill first. Queue works exactly the same.
Let's explore queues in more detail and see how to perform different operations.
What is a Queue?
A queue is a collection of elements that are arranged in such a way that the element added first is the first element that comes out. As stated earlier, it follows the FIFO principle. Like Lists<T>, it is also a generic class Queue<T> that works with generic data types. To work with queues, you must add the System.Collections.Generic; namespace in your program.
I'll skip that here since I have already demonstrated adding this namespace to your program in the previous articles. Please add the namespace in your program before trying the examples in this lesson.
Declaring a Queue
You can specify the data type and the name of the queue while declaring. The items in the queue are added via the Enqueue() method defined in the generic class Queue<T>.
Syntax:
Queue<datatype> queue_name = new Queue<datatype>();
Example:
using System;
using System.Collections.Generic;
class DataStructures {
static void Main() {
Queue<string> names = new Queue<string>();
}
}
Adding Elements to the Queue
The Queue<T> class provides the Enqueue() method to add elements to the queues.
Syntax:
queue_name.Enqueue(item);
Example:
using System;
using System.Collections.Generic;
class DataStructures {
static void Main() {
Queue<string> names = new Queue<string>();
names.Enqueue("Sanjay"); //Adds Sanjay at top
names.Enqueue("Kumar"); //Adds Kumar at top
names.Enqueue("Sandy"); //Adds Sandy at top
}
}
Removing Elements from Queue
The Queue<T> also provides the Dequeue() method to remove an element from the queue.
Syntax:
queue_name.Dequeue();
Example:
using System;
using System.Collections.Generic;
class DataStructures {
static void Main() {
Queue<string> names = new Queue<string>();
names.Enqueue("Sanjay"); //Adds Sanjay at top
names.Enqueue("Kumar"); //Adds Kumar at top
names.Enqueue("Sandy"); //Adds Sandy at top
names.Dequeue(); //Removes Sanjay from the queue
}
}
Returning the Front Element
Returning here refers to taking a look at the front element in a queue. The Peek() method is used to examine the front element of the queue without removing it. It will throw an exception if a queue is empty.
Syntax:
queue_name.Peek();
Example:
using System;
using System.Collections.Generic;
class DataStructures {
static void Main() {
Queue<string> names = new Queue<string>();
names.Enqueue("Sanjay"); //Adds Sanjay at top
names.Enqueue("Kumar"); //Adds Kumar at top
names.Enqueue("Sandy"); //Adds Sandy at top
Console.WriteLine(names.Peek()); //Returns the front element
}
}
Getting the Number of Elements in Queue
You can use the Count property to find the number of elements in a queue.
Syntax:
queue_name.Count;
Example:
using System;
using System.Collections.Generic;
class DataStructures {
static void Main() {
Queue<string> names = new Queue<string>();
names.Enqueue("Sanjay"); //Adds Sanjay at top
names.Enqueue("Kumar"); //Adds Kumar at top
names.Enqueue("Sandy"); //Adds Sandy at top
Console.WriteLine(names.Count); //Returns 3
}
}
Checking if a Queue is Empty
C# does not provide a specific function or property to check whether the queue contains elements. So, we use the Count property to determine this.
You can specify a condition where if the count of elements is 0, the queue should be shown as empty; otherwise, it contains the elements.
using System;
using System.Collections.Generic;
class DataStructures {
public static bool isEmpty(Queue q)
{
if(q.Count == 0) //Checks if the queue contains the elements
{
return true;
}
else
{
return false;
}
}
static void Main() {
Queue<string> names = new Queue<string>();
names.Enqueue("Sanjay"); //Adds Sanjay at top
names.Enqueue("Kumar"); //Adds Kumar at top
names.Enqueue("Sandy"); //Adds Sandy at top
Console.WriteLine(isEmpty(names)); //Calling the isEmpty() method. Returns False.
}
}
In the above example, we have defined a custom function that checks the elements in a queue passed to it as the parameter. If the queue is empty, it returns true. Else, it returns false.
Uses of Queues
Queues are widely used in software applications due to their FIFO functionality. Some of these use cases include:
Task Scheduling
Operating and task management systems use queues to schedule and manage tasks and processes. Whenever a new task is created, it is added to the back of the queue. The scheduler dequeues a task from the front to assign the processing time to it. This ensures that the tasks are completed in the order they are submitted so the earlier tasks do not starve.
Handling Requests in Server
In server applications, the server uses queues to manage the incoming requests. The calls are enqueued in the queues and dequeues by the worker threads to process them. With this, the servers ensure that the calls are processed in the received sequence so all clients get fair processing.
Breadth-First Search
The queues are also used in the Breadth-First search algorithm to explore the neighbor nodes at the present depth before moving to the next depth. Beginning from the root node, it enqueues all the neighbors and dequeues them one by one to explore its unvisited neighbors. This ensures that the nodes closer to the starting node are explored before those farther away. When used properly, queues can be highly beneficial for storing data conveniently. They provide an efficient way to store, retrieve, delete, and perform different operations on the data. In the next article, we will learn about the Linked Lists, a data structure that links the nodes to one another.