Circular Array implementation can be the preferred choice for Deque when the data is limited in size. This would be faster since the array has a better cache locality for the CPU.
See Deque Implementation using Doubly Linked List for dynamic and large data.
1. Representation
An array with the size of 8 is represented here in circular form for quick understanding.
// Queue maximum capacity
#define CAPACITY 8
// Deque
int queue[CAPACITY];
// Front position
int front = -1;
// Rear position
int rear = -1;
2. Implementation of Deque using Circular Array in C++
/**
* C++ example to demonstrate Deque implementation using Circular Array
*/
#include <iostream>
using namespace std;
// Queue maximum capacity
#define CAPACITY 8
/**
* Deque implementation using Circular Array
*/
class Deque
{
private:
// Queue
int queue[CAPACITY];
// Front position
int front;
// Rear position
int rear;
public:
// Constructor
Deque() : front(-1), rear(-1) {}
// Insert the new element at Front side
void insertFront(int element);
// Insert the new element at Rear side
void insertRear(int element);
// Delete the element from Front side
int deleteFront();
// Delete the element from Rear side
int deleteRear();
// Print the Queue
void display(string msg);
// Check if the Queue is empty
bool isEmpty();
// Check if the Queue is full
bool isFull();
};
// Insert the new element at Front side
void Deque::insertFront(int element) {
// Step 1. Check if the Queue is full, and return if true.
if (isFull()) {
return;
}
// Step 2. Move the Front by one position backward based on
// the below conditions
if (isEmpty()) {
// If the Front is -1 (queue is empty), initialize the
// Front and Rear to point the first index
front = rear = 0;
} else if (front == 0) {
// If the Front is 0, move Front to the last index
front = (CAPACITY-1);
} else {
// Otherwise decrement the Front by one position.
front--;
}
// Step 3. Insert the new element at Front
queue[front] = element;
}
// Insert the new element at Rear side
void Deque::insertRear(int element) {
// Step 1. Check if the Queue is full, and return if true.
if (isFull()) {
return;
}
// Step 2. Move the Rear one position forward based on
// the below conditions
if (front == -1) {
// If the Front is -1 (queue is empty), initialize the
// Front and Rear to point the first index.
front = rear = 0;
} else if (rear == (CAPACITY-1)) {
// If the Rear is at the last index, move Rear to first index
rear = 0;
} else {
// Otherwise increment the Rear by one position.
rear++;
}
// Step 3. Insert the new element at Rear
queue[rear] = element;
}
// Delete the element from Front side
int Deque::deleteFront() {
// Step 1. Check if the Queue is empty, and return if true.
if (isEmpty()) {
return -1;
}
// Step 2. Retrieve the element at Front
int element = queue[front];
// Step 3. Move the Front by one position forward based on
// the below conditions
if (front == rear) {
// If Front and Rear are at the same index, reset
// Front and Rear to -1
front = -1;
rear = -1;
} else if (front == (CAPACITY-1)) {
// If Front is at the last index, move Front to first index
front = 0;
} else {
// Otherwise increment the Front by one position
front++;
}
return element;
}
// Delete the element from Rear side
int Deque::deleteRear() {
// Step 1. Check if the Queue is empty, and return if true.
if (isEmpty()) {
return -1;
}
// Step 2. Retrieve the element at Rear
int element = queue[rear];
// Step 3. Move the Rear by one position backward based on
// the below conditions
if (front == rear) {
// If Front and Rear are at the same index, reset
// Front and Rear to -1
front = -1;
rear = -1;
} else if (rear == 0) {
// If Rear is at index 0, move Rear to last index
rear = (CAPACITY-1);
} else {
// Otherwise decrement the Rear by one position
rear--;
}
return element;
}
// Print the Queue
void Deque::display(string msg) {
cout << msg << endl;
if (isEmpty()) {
return;
}
cout << "INDEX | ELEMENT" << endl;
cout << "------+--------" << endl;
int i=front;
while (true) {
// Just frame the Front & Rear pointers to print
string ptrs = "";
if (i == front && front == rear) {
ptrs = " <-- front, rear";
} else if (i == front) {
ptrs = " <-- front";
} else if (i == rear) {
ptrs = " <-- rear";
}
// Print the element
cout << " [" << i << "] | " << queue[i] << ptrs << endl;
// Navigate to next position
if (i == rear) {
break;
} else if (i == (CAPACITY-1)) {
i = 0;
} else {
i++;
}
}
cout << endl;
}
// Check if the Queue is empty
bool Deque::isEmpty() {
if (front == -1) {
return true;
}
return false;
}
// Check if the Queue is full
bool Deque::isFull() {
if ((front == 0 && rear == (CAPACITY-1)) ||
(front == (rear+1))) {
return true;
}
return false;
}
// The main function to begin the execution
int main()
{
// Create a Deque
Deque queue;
// Insert Front
queue.insertFront(5);
queue.insertFront(3);
queue.insertFront(1);
queue.display("Queue after inserting 5, 3, and 1 at the Front side");
// Insert Rear
queue.insertRear(10);
queue.insertRear(20);
queue.insertRear(30);
queue.display("Queue after inserting 10, 20, and 30 at the Rear side");
// Delete Front
int element = queue.deleteFront();
queue.display("Queue after deleting an element at Front");
// Delete Rear
element = queue.deleteRear();
queue.display("Queue after deleting an element at Rear");
}
Output
Queue after inserting 5, 3, and 1 at the Front side
INDEX | ELEMENT
------+--------
[6] | 1 <-- front
[7] | 3
[0] | 5 <-- rear
Queue after inserting 10, 20, and 30 at the Rear side
INDEX | ELEMENT
------+--------
[6] | 1 <-- front
[7] | 3
[0] | 5
[1] | 10
[2] | 20
[3] | 30 <-- rear
Queue after deleting an element at Front
INDEX | ELEMENT
------+--------
[7] | 3 <-- front
[0] | 5
[1] | 10
[2] | 20
[3] | 30 <-- rear
Queue after deleting an element at Rear
INDEX | ELEMENT
------+--------
[7] | 3 <-- front
[0] | 5
[1] | 10
[2] | 20 <-- rear
3. Deque Operations using Circular Array
3.1. Insert Front
An element can be inserted at the front side by finding a free space prior to the Front position.
Algorithm
- Check if the Queue is full, and return if true.
- Move the Front by one position backward based on the below conditions
- If the Front is -1 (Queue is empty), then initialize the Front and Rear to point to the first index.
- If the Front is 0, move the Front to the last index.
- Otherwise, decrement the Front by one position.
- Finally, insert the new element at the Front.
Examples
The example demonstrates inserting the elements 5, 3, and 1 at the front side of an empty Deque.
- The initial Deque is empty
- So, the Front and Rear are set to -1
- If the Front is -1, then set Front and Rear to first index 0.
- Insert the new element (5) at the Front.
- If the Front is 0, set Front to the last index 7.
- Insert the new element at the Front.
- Decrement the Front by one position
- Insert the new element at the Front.
3.2. Insert Rear
An element can be inserted at the rear side by finding a free space after the Rear position.
Algorithm
- Check if the Queue is full, and return if true.
- Otherwise, move the Front by one position forward based on the below conditions
- If the Front is -1 (Queue is empty), then initialize the Front and Rear to point to the first index
- If the Rear is at the last index, move the Rear to the first index
- Otherwise, increment the Rear by one position.
- Finally, insert the new element at the Rear
Examples
The example demonstrates inserting the elements 10, 20, and 30 in Deque.
- Let’s take the following Deque and perform insertRear operations.
- Increment the Rear by one position.
- Insert the new element at the Rear.
- Increment the Rear by one position.
- Insert the new element at the Rear.
- Increment the Rear by one position.
- Insert the new element at the Rear.
3.3. Delete Front
An element can be removed from the front side by moving the Front position to the next element.
Algorithm
- Check if the Queue is empty, and return if true.
- Otherwise, retrieve the element at the Front
- Then, move the Front by one position forward based on the below conditions
- If the Front and Rear are at the same index, then reset the Front and Rear to -1
- If Front is at the last index, move Front to the first index
- Otherwise, increment the Front by one position
Examples
The example demonstrates deleting three elements from the front side of Deque.
- Let’s take the following Deque and perform deleteFront operations.
- Retrieve the element (1) at the Front.
- Increment the Front by one position.
- Retrieve the element (3) at the Front.
- IF Front = 7 (last index), set Front to 0.
- Retrieve the element (5) at the Front.
- Increment the Front by one position.
3.4. Delete Rear
An element can be removed from the rear side by moving the Rear position to the previous element.
Algorithm
- Check if the Queue is empty, and return if true.
- Otherwise, retrieve the element at the Rear
- Then, move the Rear by one position backward based on the below conditions
- If the Front and Rear are at the same index, then reset the Front and Rear to -1
- If the Rear is at index 0, move the Rear to the last index
- Otherwise, decrement the Rear by one position
Examples
The example demonstrates to deletion of three elements from the rear side of the Deque.
- Retrieve the element (30) at the Rear.
- Decrement the Front by one position.
- Retrieve the element (20) at the Rear.
- Decrement the Front by one position.
- Retrieve the element (10) at the Rear.
- If the Front and Rear are the same, then reset them to -1