C# Deque means double-ended queue. It is a linear data structure that allows us to add or remove elements from both the front and the end. A deque is more flexible than the normal queue where we can only add elements from the back and remove them from the front.
- Elements can be added or removed from both the front and end.
- The deque can grow and shrink dynamically.
- We can use deque as a Stack or Queue depending upon the use cases.
Example: This example demonstrates how to add elements to both the front and the back of the deque
C#
// demonstrating Dequeue
using System;
using System.Collections.Generic;
class Geeks
{
static void Main()
{
// Create a LinkedList to simulate a Deque
LinkedList<int> d = new LinkedList<int>();
// Add elements to the front
d.AddFirst(10);
d.AddFirst(20);
d.AddFirst(30);
// Add elements to the back
d.AddLast(50);
// Iterate over the deque and print each element
Console.WriteLine("Elements in the Deque:");
foreach (var i in d)
{
Console.WriteLine(i);
}
}
}
OutputElements in the Deque:
30
20
10
50
Why use a Deque?
Deque is very useful in scenarios where we need to manage the data from both the ends. Some of the common applications of deque are listed below:
- Job Scheduling: Managing tasks with varying priorities.
- Sliding Window Algorithms: Solving problems like finding the maximum in a subarray.
- Breadth-First Search (BFS): Traversing graphs or trees.
Types of Deque
The below diagram demonstrates the types of deque in C#.
- Input-Restricted deque: In this, insertion is allowed only at one end, but deletion can be done from both ends.
- Output-Restricted deque: In this, deletion is allowed only at one end, but insertion can be done from both ends.
- Double-Ended deque: In this, insertion and deletion are allowed at both ends.
Declaration of Deque
In C#, there is no built-in deque class. We can create deque with the help of LinkedList<T> class or by using Queue<T> class.
Note: Queue<T> can also create a deque, but it is not ideal for operation at both the ends due to limitations.
Using LinkedList<T> (Recommended Approach)
A LinkedList<T> is a good choice for a deque because it lets us add or remove items quickly from both the front and back.
Declaration of deque using LinkedList<T>
LinkedList<int> deque = new LinkedList<int>();
Example: This example, demonstrates how to add elements to both the front and back and then iterating through the list
C#
// demonstrates using LinkedList<T> class
using System;
using System.Collections.Generic;
class Geeks
{
static void Main()
{
// Declare a LinkedList as a Deque
LinkedList<int> d = new LinkedList<int>();
// Add elements to the front (AddFirst)
d.AddFirst(10);
d.AddFirst(20);
d.AddFirst(30);
// Add elements to the back (AddLast)
d.AddLast(40);
d.AddLast(50);
// Iterate over the deque and print elements
Console.WriteLine("Deque Elements:");
foreach (var i in d)
{
Console.WriteLine(i);
}
}
}
OutputDeque Elements:
30
20
10
40
50
Implementing Deque in C#
C# provides Three approaches to implement deque in C#, we are going to discuss about each approach one by one
1. Implementing Deque using Arrays
An Array-based deque can be implemented by managing a fixed-size array and keeping track of front and rear pointers.
Implementation:
C#
// demonstrating how to implement dequeue
// using array
using System;
public class SimpleDequeue
{
private int[] arr;
private int front;
private int rear;
private int size;
public SimpleDequeue(int capacity)
{
arr = new int[capacity];
front = -1;
rear = -1;
size = 0;
}
// Add to the front of the deque
public void EnqueueFront(int value)
{
if (size == arr.Length)
{
Console.WriteLine("Queue is full");
return;
}
if (front == -1) // If it's the first element
{
front = 0;
rear = 0;
}
else if (front == 0) // Wrap around if front is at 0
{
front = arr.Length - 1;
}
else
{
front--;
}
arr[front] = value;
size++;
}
// Add to the rear of the deque
public void EnqueueRear(int value)
{
if (size == arr.Length)
{
Console.WriteLine("Queue is full");
return;
}
// If it's the first element
if (front == -1)
{
front = 0;
rear = 0;
}
else
{
// Wrap around if rear is at the end
rear = (rear + 1) % arr.Length;
}
arr[rear] = value;
size++;
}
// Remove from the front of the deque
public int DequeueFront()
{
if (size == 0)
{
Console.WriteLine("Queue is empty");
return -1;
}
int removedValue = arr[front];
// Only one element in the queue
if (front == rear)
{
front = -1;
rear = -1;
}
else
{
// Move the front pointer
front = (front + 1) % arr.Length;
}
size--;
return removedValue;
}
// Remove from the rear of the deque
public int DequeueRear()
{
if (size == 0)
{
Console.WriteLine("Queue is empty");
return -1;
}
int removedValue = arr[rear];
// Only one element in the queue
if (front == rear)
{
front = -1;
rear = -1;
}
else
{
// Move the rear pointer
rear = (rear - 1 + arr.Length) % arr.Length;
}
size--;
return removedValue;
}
// Display the current elements in the deque
public void Display()
{
if (size == 0)
{
Console.WriteLine("Queue is empty");
return;
}
int i = front;
for (int count = 0; count < size; count++)
{
Console.Write(arr[i] + " ");
i = (i + 1) % arr.Length;
}
Console.WriteLine();
}
}
class Geeks
{
static void Main()
{
SimpleDequeue dq = new SimpleDequeue(5);
// Adding elements to both ends
dq.EnqueueRear(10);
dq.EnqueueRear(20);
dq.EnqueueFront(30);
dq.EnqueueFront(40);
dq.Display();
// Removing elements from both ends
Console.WriteLine("Dequeue from front: " + dq.DequeueFront());
Console.WriteLine("Dequeue from rear: " + dq.DequeueRear());
dq.Display();
}
}
Output40 30 10 20
Dequeue from front: 40
Dequeue from rear: 20
30 10
2. Implementing Deque using LinkedList
LinkedList<T> class is an ideal choice for deque because it allows fast insertion and deletion operations from both ends. The LinkedList<T> stores elements in a doubly-linked list, both ends can be accessed and modified in constant time O(1).
Implementation:
C++
// demonstrating how to implement dequeue
// using LinkedList
using System;
using System.Collections.Generic;
class Geeks {
static void Main() {
LinkedList<int> d = new LinkedList<int>();
// Adding element to the front of the dequeue
d.AddFirst(10);
d.AddFirst(20);
// Adding element to the back of the dequeue
d.AddLast(30);
d.AddLast(40);
// Removing element from the front of the dequeue
int front = d.First.Value;
d.RemoveFirst();
// Removing element from the back of the dequeue
int back = d.Last.Value;
d.RemoveLast();
// Display the remaining elements of the dequeue
foreach (int i in d) {
Console.WriteLine(i);
}
}
}
Output:
3. Implementing Deque Using List<T>
A list<T> is dynamic array, it can efficiently access elements by index. This approach is less efficient for the front operations (add/remove) compared to the LinkedList<T> approach but can still be useful for small lists.
Implementation:
C#
// demonstrating how to implement dequeue
// using List
using System;
using System.Collections.Generic;
class Geeks{
static void Main() {
List<int> d = new List<int>();
// Adding elements to the front of the dequeue
d.Insert(0, 10);
d.Insert(0, 20);
// Adding elements to the back of the dequeue
d.Add(30);
d.Add(40);
// Removing element from the front of the dequeue
int front = d[0];
d.RemoveAt(0);
// Removing element from the back of the dequeue
int back = d[d.Count - 1];
d.RemoveAt(d.Count - 1);
// Display the remaining elements of the dequeue
foreach (int value in d) {
Console.WriteLine(value);
}
}
}
Performing Various Operations on Deque
1. Adding Elements to the Front
We can use the EnqueueFront() to add elements to the front of the deque.
Example: This example demonstrates how to insert elements to the front of the deque.
C#
// demonstrating the working of EnqueueFront()
using System;
public class SimpleDequeue
{
private int[] arr;
private int front;
private int rear;
private int size;
public SimpleDequeue(int capacity)
{
arr = new int[capacity];
front = -1;
rear = -1;
size = 0;
}
// Add to the front of the deque
public void EnqueueFront(int value)
{
if (size == arr.Length)
{
Console.WriteLine("Deque is full!");
return;
}
// If it's the first element
if (front == -1)
{
front = 0;
rear = 0;
}
// Wrap around if front is at 0
else if (front == 0)
{
front = arr.Length - 1;
}
else
{
front--;
}
arr[front] = value;
size++;
}
// Display the current elements in the deque
public void Display()
{
if (size == 0)
{
Console.WriteLine("Deque is empty!");
return;
}
int i = front;
for (int count = 0; count < size; count++)
{
Console.Write(arr[i] + " ");
i = (i + 1) % arr.Length;
}
Console.WriteLine();
}
}
class Geeks
{
static void Main()
{
SimpleDequeue dq = new SimpleDequeue(5);
// Add elements to the front
dq.EnqueueFront(10);
dq.EnqueueFront(20);
dq.EnqueueFront(30);
// Display the deque after adding to the front
dq.Display();
}
}
Output:
2. Adding Element to the Rear
We can use the EnqueueRear() to add elements to the end of the deque.
Example:
C#
using System;
public class SimpleDequeue
{
private int[] arr;
private int front;
private int rear;
private int size;
public SimpleDequeue(int capacity)
{
arr = new int[capacity];
front = -1;
rear = -1;
size = 0;
}
// Adding element to the rear of the dequeue
public void EnqueueRear(int value)
{
if (size == arr.Length)
{
Console.WriteLine("Deque is full!");
return;
}
// If it's the first element
if (front == -1)
{
front = 0;
rear = 0;
}
else
{
// Wrap around if rear is at the end
rear = (rear + 1) % arr.Length;
}
arr[rear] = value;
size++;
}
// Displaying the current elements in the dequeue
public void Display()
{
if (size == 0)
{
Console.WriteLine("Deque is empty!");
return;
}
int i = front;
for (int count = 0; count < size; count++)
{
Console.Write(arr[i] + " ");
i = (i + 1) % arr.Length;
}
Console.WriteLine();
}
}
class Geeks
{
static void Main()
{
SimpleDequeue dq = new SimpleDequeue(5);
// Adding elements to the rear
dq.EnqueueRear(10);
dq.EnqueueRear(20);
dq.EnqueueRear(30);
// Displaying the deque after adding to the rear
dq.Display();
}
}
Output:
3. Removing Elements from the Front
We can use the dequeFront() method to remove elements from the front of the deque.
Example:
C#
using System;
public class SimpleDequeue
{
private int[] arr;
private int front;
private int rear;
private int size;
public SimpleDequeue(int capacity)
{
arr = new int[capacity];
front = -1;
rear = -1;
size = 0;
}
// Add to the rear of the deque
public void EnqueueRear(int value)
{
if (size == arr.Length)
{
Console.WriteLine("Deque is full!");
return;
}
// If it's the first element
if (front == -1)
{
front = 0;
rear = 0;
}
else
{
rear = (rear + 1) % arr.Length;
}
arr[rear] = value;
size++;
}
// Remove from the front of the deque
public int DequeueFront()
{
if (size == 0)
{
Console.WriteLine("Deque is empty!");
return -1;
}
int removedValue = arr[front];
if (front == rear) // Only one element in the deque
{
front = -1;
rear = -1;
}
else
{
// Move the front pointer
front = (front + 1) % arr.Length;
}
size--;
return removedValue;
}
// Display the current elements in the deque
public void Display()
{
if (size == 0)
{
Console.WriteLine("Deque is empty!");
return;
}
int i = front;
for (int count = 0; count < size; count++)
{
Console.Write(arr[i] + " ");
i = (i + 1) % arr.Length;
}
Console.WriteLine();
}
}
class Geeks
{
static void Main()
{
SimpleDequeue dq = new SimpleDequeue(5);
// Add elements to the rear
dq.EnqueueRear(10);
dq.EnqueueRear(20);
dq.EnqueueRear(30);
// Remove elements from the front
Console.WriteLine($"Removed from front: {dq.DequeueFront()}");
dq.Display();
}
}
Output:
4. Removing Elements from the Rear
We can use the dequeRear() method to remove elements from the end of the deque.
Example:
C#
using System;
public class SimpleDequeue
{
private int[] arr;
private int front;
private int rear;
private int size;
public SimpleDequeue(int capacity)
{
arr = new int[capacity];
front = -1;
rear = -1;
size = 0;
}
// Add to the rear of the deque
public void EnqueueRear(int value)
{
if (size == arr.Length)
{
Console.WriteLine("Deque is full!");
return;
}
// If it's the first element
if (front == -1)
{
front = 0;
rear = 0;
}
else
{
rear = (rear + 1) % arr.Length;
}
arr[rear] = value;
size++;
}
// Remove from the rear of the deque
public int DequeueRear()
{
if (size == 0)
{
Console.WriteLine("Deque is empty!");
return -1;
}
int removedValue = arr[rear];
// Only one element in the deque
if (front == rear)
{
front = -1;
rear = -1;
}
else
{
// Move the rear pointer
rear = (rear - 1 + arr.Length) % arr.Length;
}
size--;
return removedValue;
}
// Display the current elements in the deque
public void Display()
{
if (size == 0)
{
Console.WriteLine("Deque is empty!");
return;
}
int i = front;
for (int count = 0; count < size; count++)
{
Console.Write(arr[i] + " ");
i = (i + 1) % arr.Length;
}
Console.WriteLine();
}
}
class Geeks
{
static void Main()
{
SimpleDequeue dq = new SimpleDequeue(5);
// Add elements to the rear
dq.EnqueueRear(10);
dq.EnqueueRear(20);
dq.EnqueueRear(30);
// Remove elements from the rear
Console.WriteLine($"Removed from rear: {dq.DequeueRear()}");
dq.Display();
}
}
Output:
Similar Reads
Introduction
C# TutorialC# (pronounced "C-sharp") is a modern, versatile, object-oriented programming language developed by Microsoft in 2000 that runs on the .NET Framework. Whether you're creating Windows applications, diving into Unity game development, or working on enterprise solutions, C# is one of the top choices fo
4 min read
Introduction to .NET FrameworkThe .NET Framework is a software development framework developed by Microsoft that provides a runtime environment and a set of libraries and tools for building and running applications on Windows operating systems. The .NET framework is primarily used on Windows, while .NET Core (which evolved into
6 min read
C# .NET Framework (Basic Architecture and Component Stack)C# (C-Sharp) is a modern, object-oriented programming language developed by Microsoft in 2000. It is a part of the .NET ecosystem and is widely used for building desktop, web, mobile, cloud, and enterprise applications. This is originally tied to the .NET Framework, C# has evolved to be the primary
6 min read
C# Hello WorldThe Hello World Program is the most basic program when we dive into a new programming language. This simply prints "Hello World!" on the console. In C#, a basic program consists of the following:A Namespace DeclarationClass Declaration & DefinitionClass Members(like variables, methods, etc.)Main
4 min read
Common Language Runtime (CLR) in C#The Common Language Runtime (CLR) is a component of the Microsoft .NET Framework that manages the execution of .NET applications. It is responsible for loading and executing the code written in various .NET programming languages, including C#, VB.NET, F#, and others.When a C# program is compiled, th
4 min read
Fundamentals
C# IdentifiersIn programming languages, identifiers are used for identification purposes. Or in other words, identifiers are the user-defined name of the program components. In C#, an identifier can be a class name, method name, variable name, or label. Example: public class GFG { static public void Main () { int
2 min read
C# Data TypesData types specify the type of data that a valid C# variable can hold. C# is a strongly typed programming language because in C# each type of data (such as integer, character, float, and so forth) is predefined as part of the programming language and all constants or variables defined for a given pr
7 min read
C# VariablesIn C#, variables are containers used to store data values during program execution. So basically, a Variable is a placeholder of the information which can be changed at runtime. And variables allows to Retrieve and Manipulate the stored information. In Brief Defination: When a user enters a new valu
4 min read
C# LiteralsIn C#, a literal is a fixed value used in a program. These values are directly written into the code and can be used by variables. A literal can be an integer, floating-point number, string, character, boolean, or even null. Example:// Here 100 is a constant/literal.int x = 100; Types of Literals in
5 min read
C# OperatorsIn C#, Operators are special types of symbols which perform operations on variables or values. It is a fundamental part of language which plays an important role in performing different mathematical operations. It takes one or more operands and performs operations to produce a result.Types of Operat
7 min read
C# KeywordsKeywords or Reserved words are the words in a language that are used for some internal process or represent some predefined actions. These words are therefore not allowed to be used as variable names or objects. Doing this will result in a compile-time error.Example:C#// C# Program to illustrate the
5 min read
Control Statements
C# Decision Making (if, if-else, if-else-if ladder, nested if, switch, nested switch)Decision Making in programming is similar to decision making in real life. In programming too, a certain block of code needs to be executed when some condition is fulfilled. A programming language uses control statements to control the flow of execution of program based on certain conditions. These
5 min read
C# Switch StatementIn C#, Switch statement is a multiway branch statement. It provides an efficient way to transfer the execution to different parts of a code based on the value of the expression. The switch expression is of integer type such as int, char, byte, or short, or of an enumeration type, or of string type.
4 min read
C# LoopsLooping in a programming language is a way to execute a statement or a set of statements multiple times, depending on the result of the condition to be evaluated to execute statements. The result condition should be true to execute statements within loops.Types of Loops in C#Loops are mainly divided
4 min read
C# Jump Statements (Break, Continue, Goto, Return and Throw)In C#, Jump statements are used to transfer control from one point to another point in the program due to some specified code while executing the program. In, this article, we will learn to different jump statements available to work in C#.Types of Jump StatementsThere are mainly five keywords in th
4 min read
OOP Concepts
Methods
Arrays
C# ArraysAn array is a group of like-typed variables that are referred to by a common name. And each data item is called an element of the array. The data types of the elements may be any valid data type like char, int, float, etc. and the elements are stored in a contiguous location. Length of the array spe
8 min read
C# Jagged ArraysA jagged array is an array of arrays, where each element in the main array can have a different length. In simpler terms, a jagged array is an array whose elements are themselves arrays. These inner arrays can have different lengths. Can also be mixed with multidimensional arrays. The number of rows
4 min read
C# Array ClassArray class in C# is part of the System namespace and provides methods for creating, searching, and sorting arrays. The Array class is not part of the System.Collections namespace, but it is still considered as a collection because it is based on the IList interface. The Array class is the base clas
7 min read
How to Sort an Array in C# | Array.Sort() Method Set - 1Array.Sort Method in C# is used to sort elements in a one-dimensional array. There are 17 methods in the overload list of this method as follows:Sort<T>(T[]) MethodSort<T>(T[], IComparer<T>) MethodSort<T>(T[], Int32, Int32) MethodSort<T>(T[], Comparison<T>) Method
8 min read
How to find the rank of an array in C#Array.Rank Property is used to get the rank of the Array. Rank is the number of dimensions of an array. For example, 1-D array returns 1, a 2-D array returns 2, and so on. Syntax: public int Rank { get; } Property Value: It returns the rank (number of dimensions) of the Array of type System.Int32. B
2 min read
ArrayList
String
Tuple
Indexers