#18.Journey to DSA in C++

#18.Journey to DSA in C++

ยท

13 min read

๐Ÿš€ Unlocking the Magic of Queues: A Journey into Implementation and Concepts

Hello, fellow learners and coding enthusiasts! ๐Ÿ‘‹ Today, we're diving into the captivating world of queues, a data structure that's as fascinating as it is essential. I'll be your guide on this quest as we explore the implementation, techniques, and key concepts that make queues so intriguing.

The Wonders of Queues ๐ŸŽฉ

Think of a queue as a line of people waiting to buy tickets for their favorite movie. The first in line gets their ticket first. That's the essence of a queue: "First-In-First-Out" (FIFO). In simple terms, the first item added to a queue is the first to be removed. Let's unlock the magic together.

Code in C/C++

#include<stdio.h>
#define SIZE 5

//Basic value initialization
int queue[SIZE], front = -1, rear = -1;

void Enqueue(int val){
    if(rear == SIZE-1)
        printf("Encountered Overflow Condition\n");
    else{
        //When adding initial element
        if(front == -1)
            front = 0;

        rear++;
        queue[rear] = val;
        printf("%d was enqueued\n",val);
   }
}
void Dequeue(){
    if(front == -1)
        printf("Underflow condition\n");
    else{
        printf("Dequeued : %d\n", queue[front]);
        front++;

        //resetting the queue when last item is Dequeued 
        if(front > rear)
            front = rear = -1;
   }
}
void display(){
    if(rear == -1)
        printf("\nQueue is empty");
   else{
        int i;
        printf("\nNow, we are printing the Queue :");

        for(i=front; i<=rear; i++)
            printf("%d ",queue[i]);
   }
}

int main()
{
   Enqueue(10);
   Enqueue(20);
   Enqueue(30);
   Enqueue(40);

   Dequeue();
   Dequeue();

   display();
   return 0;
}

Code in C/C++:

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

// creating a structure to hold the queue 
struct myQueue 
{ 
    int front, rear;
    unsigned size; 
    //here we have created a pointer which will point to memory of array
    //created later in createQueue function 
    int* array; 
}; 

// initialise the queue 
struct myQueue* createQueue(unsigned size) 
{ 
    struct myQueue* queue = (struct myQueue*) malloc(sizeof(struct myQueue)); 
    queue->size = size;
    queue->front = -1;
    queue->rear = -1;

    //Memory is created for the array
    queue->array = (int*) malloc(queue->size * sizeof(int)); 
    return queue; 
} 

// Will return true if queue size has reached capacity 
int isFull(struct myQueue* queue)
{
    if(queue->rear == queue->size -1)
        printf("Overflow condition\n");

    return (queue->rear == queue->size -1);
} 

// Will return true if the queue is empty
int isEmpty(struct myQueue* queue) 
{
    if(queue->front == -1)
        printf("Underflow Condition\n");

    return (queue->front == -1); 
} 

// function to Enqueue in the queue and change relevant values 
void enqueue(struct myQueue* queue, int item) 
{ 
    if (isFull(queue)) 
        return; 

    if(queue->front == -1)
        queue->front = 0;

    queue->rear++;
    queue->array[queue->rear] = item;
    printf("%d added to the queue\n", item); 
} 

// Function is deuque from queue and change relevant values
void dequeue(struct myQueue* queue) 
{ 
    if (isEmpty(queue)) 
        return;

    int item = queue->array[queue->front]; 
    queue->front++;

    //resetting the queue when last item is Dequeued 
    if(queue->front > queue->rear)
       queue->front = queue->rear = -1;

    printf("%d dequeued from queue\n", item);
}

//function to display the queue
void display(struct myQueue* queue)
{
    if(queue->rear == -1)
        printf("\nQueue was Empty!!!");
   else{
        int i;
        printf("\nQueue :\n");

        for(i=queue->front; i<=queue->rear; i++)
            printf("%d ",queue->array[i]);
   }
}

// Main function
int main() 
{ 
    struct myQueue* queue = createQueue(5); 

    enqueue(queue, 10);
    enqueue(queue, 20); 
    enqueue(queue, 30); 
    enqueue(queue, 40);

    dequeue(queue);
    dequeue(queue);


    display(queue);

    return 0; 
}

Code in C/C++ (removing the Limitation)

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

// Basic struct for queue
struct Queue 
{ 
    int front, rear, currSize; 
    unsigned maxCapacity; 
    // we are storing string in integer array, this will not give error
    // as values will be stored in ASCII and returned in ASCII thus, returned as string again
    int* array; 
}; 

// Here we initialize queue and init. Current size of queue to 0  
struct Queue* createQueue(unsigned maxCapacity) 
{ 
    struct Queue* queue = (struct Queue*) malloc(sizeof(struct Queue)); 
    queue->maxCapacity = maxCapacity;
    queue->front = queue->currSize = 0;
    queue->rear = maxCapacity - 1;  // This is important, see the enqueue 
    queue->array = (int*) malloc(queue->maxCapacity * sizeof(int)); 
    return queue; 
} 

// Will return true if queue Current size has reached maxCapacity 
int isFull(struct Queue* queue) 
{
    if(queue->currSize == queue->maxCapacity)
        printf("Can't insert as queue is full\n");

    return (queue->currSize == queue->maxCapacity);  
} 

// Will return true if queue Current size is 0
int isEmpty(struct Queue* queue) 
{  
    if(queue->currSize == 0)
        printf("Can't deuque as queue is empty\n");
    return (queue->currSize == 0); 
} 

// Here we add new item to queue and change rear and Current size  
void enqueue(struct Queue* queue, int item) 
{ 
    if (isFull(queue)) 
        return; 

    //Bcz, queue->rear is set up to maxCapacity adding + 1 
    //and % maxCapacity will set rear to start of queue
    //enqueue happens at the rear value always so to maintain First in first out 
    queue->rear = (queue->rear + 1)%queue->maxCapacity; 
    queue->array[queue->rear] = item; 
    queue->currSize = queue->currSize + 1; 
    printf("%d added to the queue at array pos:%d\n", item,queue->rear); 
} 

// Here we remove or dequeue from queue and 
//also change the front value and Current size of queue  
void dequeue(struct Queue* queue) 
{ 
    if (isEmpty(queue)) 
        return; 
    int item = queue->array[queue->front]; 
    queue->front = (queue->front + 1)%queue->maxCapacity; 
    queue->currSize = queue->currSize - 1;
    printf("\n%d dequeued from queue, new front is at pos:%d\n", item,queue->front);
}

void display(struct Queue* queue)
{
    if(queue->currSize == 0)
        printf("\nQueue was Empty!!!");
   else{
        int i=queue->front, j;
        printf("\nQueue :\n");

        for(j=0; j<queue->currSize; j++)
            printf("%d ",queue->array[(i+j)%queue->maxCapacity]);
   }
}
// Main function to run queue program
int main() 
{ 
    struct Queue* queue = createQueue(5); 

    enqueue(queue,10);
    enqueue(queue,20);
    enqueue(queue,30);
    enqueue(queue,40);


    dequeue(queue);
    dequeue(queue);

    enqueue(queue,50);
    enqueue(queue,60);

    display(queue);
    return 0; 
}

Code in C++ (Class Implementation with Private Variables)

#include <bits/stdc++.h>
using namespace std;

// Basic struct for queue
class Queue 
{
    private: 
        int front, rear, currSize; 
        unsigned maxCapacity; 
        int* array;
    public:

    Queue(int size){
        maxCapacity = size;
        front = 0;
        currSize = 0;
        rear = maxCapacity - 1;
        array = new int [maxCapacity];
    }
    void enqueue(int x);
    void dequeue();
    bool isEmpty();
    bool isFull();
    void display();

}; 

// Will return true if queue Current size has reached maxCapacity 
bool Queue::isFull() 
{
    if(currSize == maxCapacity)
        cout << "Can't insert as queue is full\n";

    return (currSize == maxCapacity);  
} 

// Will return true if queue Current size is 0
bool Queue::isEmpty() 
{  
    if(currSize == 0)
        cout << "Can't deque as queue is empty\n";
    return (currSize == 0); 
} 

// Here we add new item to queue and change rear and Current size  
void Queue::enqueue(int item) 
{ 
    if (isFull()) 
        return; 

    //Bcz, rear is set up to maxCapacity adding + 1 
    //and % maxCapacity will set rear to start of queue
    //enqueue happens at the rear value always so to maintain First in first out 
    rear = (rear + 1)%maxCapacity; 
    array[rear] = item; 
    currSize = currSize + 1; 
    cout << item << " added to the queue at array pos:" << rear << endl; 
} 

// Here we remove or dequeue from queue and 
//also change the front value and Current size of queue  
void Queue::dequeue() 
{ 
    if (isEmpty())
        return; 
    int item = array[front]; 
    front = (front + 1)%maxCapacity; 
    currSize = currSize - 1;
    cout << item << " dequeued from queue, new front is at pos:" << front << endl;
}

void Queue::display()
{
    if(currSize == 0)
        cout << "\nQueue was Empty!!!";
   else{
        int i,j;
        cout <<"\nQueue :\n";

        for(i=front,j=0; j<currSize; j++)
            cout << array[(i+j) % maxCapacity] << " ";
   }
}
// Main function to run queue program
int main() 
{ 
    Queue queue = Queue(5); 

    queue.enqueue(10);
    queue.enqueue(20);
    queue.enqueue(30);
    queue.enqueue(40);

    cout << endl;

    queue.dequeue();
    queue.dequeue();

    cout << endl;

    queue.enqueue(50);
    queue.enqueue(60);

    queue.display();

    return 0; 
}

Code in C++ (Class Implementation with Public Variables)

#include <bits/stdc++.h>
using namespace std;

// A structure to represent a queue
class Queue {
public:
    int front, rear, size;
    unsigned capacity;
    int* array;
};

Queue* createQueue(unsigned capacity)
{
    Queue* queue = new Queue();
    queue->capacity = capacity;
    queue->front = queue->size = 0;

    queue->rear = capacity - 1;
    queue->array = new int[queue->capacity];
    return queue;
}


bool isFull(Queue* queue)
{
    return (queue->size == queue->capacity);
}

bool isEmpty(Queue* queue)
{
    return (queue->size == 0);
}

void enqueue(Queue* queue, int item)
{
    if (isFull(queue))
        return;
    queue->rear = (queue->rear + 1)
                  % queue->capacity;
    queue->array[queue->rear] = item;
    queue->size = queue->size + 1;
    cout << item << " is enqueued to Queue\n";
}

int dequeue(Queue* queue)
{
    if (isEmpty(queue))
        return INT_MIN;
    int item = queue->array[queue->front];
    queue->front = (queue->front + 1)
                   % queue->capacity;
    queue->size = queue->size - 1;
    return item;
}

int front(Queue* queue)
{
    if (isEmpty(queue))
        return INT_MIN;
    return queue->array[queue->front];
}

int rear(Queue* queue)
{
    if (isEmpty(queue))
        return INT_MIN;
    return queue->array[queue->rear];
}

// Driver code
int main()
{
    Queue* queue = createQueue(5);

    enqueue(queue, 10);
    enqueue(queue, 20);
    enqueue(queue, 30);
    enqueue(queue, 40);

    cout << "\n" << dequeue(queue)
         << " dequeued from Queue\n"<< endl;

    cout << "Front: "
         << front(queue) << endl;
    cout << "Rear: "
         << rear(queue) << endl;

    return 0;
}

C++ STL Implementation of Queues

#include <iostream>
#include <queue>

using namespace std;

int main(){
    queue <int> q; 
    q.push(10); // void type
    q.push(20); 
    q.push(30); 
    q.push(40); 
    q.push(50); 

    cout << "Size: " << q.size() << endl;
    cout << "Front,Rear: " << q.front() << "," << q.back() << endl;
    q.pop(); // void type
    cout << "Front,Rear: " << q.front() << "," << q.back() << endl;

    queue <int> q2 (q); 
    cout << "Size: " << q2.size() << endl;

    cout << "\nQueue: ";
    while(!q.empty())
    {
       cout << q.front() << " ";
       q.pop();
    }


    return 0;
}

Code in C:

#include <stdio.h>
#include <stdlib.h>

struct Queue 
{ 
    int front, rear, currSize; 
    unsigned maxSize; 
    int* a;
}; 

struct Queue* createQueue(unsigned maxSize) 
{ 
    struct Queue* queue = (struct Queue*) malloc(sizeof(struct Queue)); 
    queue->maxSize = maxSize;
    queue->front = queue->rear = -1;
    queue->a = (int*) malloc(queue->maxSize * sizeof(int)); 
    return queue; 
} 

// Checking for Overflow condition
int isFull(struct Queue* queue){
    if ((queue->front == queue->rear + 1) || 
    (queue->front == 0 && queue->rear == queue->maxSize - 1)){
        return 1;
    }
    return 0;
}

// Checking for Underflow condition
int isEmpty(struct Queue* queue){
    if (queue->front == -1) 
    {
        return 1;
    }
  return 0;
}

// Function to do enqueue
void enqueue(struct Queue* queue,int value){
    if (isFull(queue))
        printf("Can't add the queue is full \n");

    else
    {
        if (queue->front == -1) 
            queue->front = 0;

        queue->rear = (queue->rear + 1) % queue->maxSize;
        queue->a[queue->rear] = value;
        printf("%d was added\n", value);
  }
}

// Function to do dequeue
int dequeue(struct Queue* queue)
{
    int item;
    if (isEmpty(queue)) 
    {
        printf("Can't add the queue is empty \n");
        return (-1);
    } 
    else
    {
        item = queue->a[queue->front];
        if (queue->front == queue->rear) 
        {
            queue->front = queue->rear = -1 ;
        } 
        else 
        {
            queue->front = (queue->front + 1) % queue->maxSize;
        }
        printf("%d dequeued\n", item);
    }
}

// Function to print the queue
void print(struct Queue* queue) {
  int i;
  if (isEmpty(queue))
    printf("Empty Queue\n");
  else {

    printf("\nThe items in the queue are : \n");
    for (i = queue->front; i != queue->rear; i = (i + 1) % queue->maxSize) {
      printf("%d ", queue->a[i]);
    }
    printf("%d \n\n", queue->a[i]);

  }
}

int main() {
  struct Queue* queue = createQueue(6);
  dequeue(queue);//Underflow condition

  enqueue(queue,12);
  enqueue(queue,14);
  enqueue(queue,16);
  enqueue(queue,18);
  enqueue(queue,20);

  print(queue);
  dequeue(queue);
  dequeue(queue);

  print(queue);

  enqueue(queue,22);
  enqueue(queue,24);
  enqueue(queue,26);
  enqueue(queue,28);//Overflow condition
  print(queue);

  return 0;
}

Code in C++:

#include <bits/stdc++.h>
using namespace std;

// Basic class for queue
class Queue 
{
    private: 
        int front, rear, currSize; 
        unsigned maxCapacity; 
        int* a;
    public:

    Queue(int size){
        maxCapacity = size;
        front = -1;
        currSize = 0;
        rear = -1;
        a = new int [maxCapacity];
    }
    void enqueue(int x);
    int dequeue();
    bool isEmpty();
    bool isFull();
    void display();

}; 

// Will return true if queue Current size has reached maxCapacity 
bool Queue::isFull() 
{
    if ((front == rear + 1) || 
    (front == 0 && rear == maxCapacity - 1)){
        return true;
    }
    return false; 
} 

// Will return true if queue Current size is 0
bool Queue::isEmpty() 
{  
    if (front == -1) 
    {
        return true;
    }
  return false;
} 

// Here we add new item to queue and change rear and Current size  
void Queue::enqueue(int item) 
{ 
    if (isFull())
        printf("Can't add the queue is full \n");

    else
    {
        if (front == -1) 
            front = 0;

        rear = (rear + 1) % maxCapacity;
        a[rear] = item;
        printf("%d was added\n", item);
  }
} 

// Here we remove or dequeue from queue and 
//also change the front value and Current size of queue  
int Queue::dequeue() 
{ 
int item;
    if (isEmpty()) 
    {
        printf("Can't add the queue is empty \n");
        return (INT_MIN);
    }
    else
    {
        item = a[front];
        if (front == rear) 
        {
            front = rear = -1 ;
        } 
        else 
        {
            front = (front + 1) % maxCapacity;
        }
        printf("%d dequeued\n", item);
        return item;
    }
}

void Queue::display()
{
  int i;
  if (isEmpty())
    printf("Empty Queue\n");
  else {

    printf("\nQueue: ");
    for (i = front; i != rear; i = (i + 1) % maxCapacity) {
      printf("%d ", a[i]);
    }
    printf("%d \n\n", a[i]);

  }
}
// Main function to run queue program
int main() 
{ 
    Queue queue = Queue(6); 

    queue.dequeue();//Underflow condition

    queue.enqueue(12);
    queue.enqueue(14);
    queue.enqueue(16);
    queue.enqueue(18);
    queue.enqueue(20);

    queue.display();
    queue.dequeue();
    queue.dequeue();

    queue.display();

    queue.enqueue(22);
    queue.enqueue(24);
    queue.enqueue(26);
    queue.enqueue(28);//Overflow condition
    queue.display();

    return 0; 
}

Code in Java:

package DSA;

class CircularQueue {
    int front, rear;
    int capacity;
    int curr_size;
    int[] a;

    CircularQueue(int cap)
    {
        capacity = cap;
        front = -1;
        rear = -1;
        curr_size = 0;
        a = new int[capacity];
    }

    boolean isFull()
    {
        return (front == rear + 1) ||
                (front == 0 && rear == capacity - 1);
    }

    boolean isEmpty()
    {
        return front == -1;
    }

    // Method to add an item to the queue.
    // It changes rear and size
    void enqueue(int item)
    {
        if (isFull())
            System.out.println("Can't add the queue is full ");

        else
        {
            if (front == -1)
                front = 0;

            rear = (rear + 1) % capacity;
            a[rear] = item;
            System.out.println(item + " was added");
        }
    }

    // Method to remove an item from queue.
    // It changes front and size
    int dequeue()
    {
        int item;
        if (isEmpty())
        {
            System.out.println("Can't add the queue is empty");
            return (Integer.MIN_VALUE);
        }
        else
        {
            item = a[front];
            if (front == rear)
            {
                front = rear = -1 ;
            }
            else
            {
                front = (front + 1) % capacity;
            }
            System.out.println(item +  " dequeued");
            return item;
        }
    }

    // Method to get front of queue
    int front()
    {
        if (isEmpty())
            return Integer.MIN_VALUE;

        return a[front];
    }

    // Method to get rear of queue
    int rear()
    {
        if (isEmpty())
            return Integer.MIN_VALUE;

        return a[rear];
    }

    void display()
    {
        int i;
        if (isEmpty())
            System.out.println("Empty Queue");
        else {

            System.out.println("\nQueue: ");
            for (i = front; i != rear; i = (i + 1) % capacity) {
                System.out.print(a[i]+ " ");
            }
            System.out.println(a[i]);

        }
    }
}

// Driver class
class Temp {
    public static void main(String[] args)
    {
        CircularQueue queue = new CircularQueue(6);

        queue.dequeue();//Underflow condition

        queue.enqueue(12);
        queue.enqueue(14);
        queue.enqueue(16);
        queue.enqueue(18);
        queue.enqueue(20);

        queue.display();
        queue.dequeue();
        queue.dequeue();

        queue.display();

        queue.enqueue(22);
        queue.enqueue(24);
        queue.enqueue(26);
        queue.enqueue(28);//Overflow condition
        queue.display();

    }
}

Code in Python:

from sys import maxsize


class Queue:
    def __init__(self, cap):
        self.queue = [None] * cap
        self.capacity = cap
        self.front = -1
        self.rear = -1
        self.curr_size = 0

    def is_full(self):
        return (self.front == self.rear + 1) or (self.front == 0 and self.rear == self.capacity - 1)

    def is_empty(self):
        return self.front == -1

    def enqueue(self, item):
        if self.is_full():
            print("Can't add the queue is full ")

        else:
            if self.front == -1:
                self.front = 0

            self.rear = (self.rear + 1) % self.capacity
            self.queue[self.rear] = item
            print(item, " was added")

    def dequeue(self):
        item = None
        if self.is_empty():
            print("Can't add the queue is empty");
            return -maxsize
        else:
            item = self.queue[self.front]

            if self.front == self.rear:
                self.front = self.rear = -1
            else:
                self.front = (self.front + 1) % self.capacity

            print(item, " dequeued")
            return item

    # function to display the queue
    def display(self):
        i = 0
        if self.is_empty():
            print("Empty Queue")
        else:
            print("\nQueue: ")
            i = self.front
            while i != self.rear:
                print(self.queue[i], end=" ")
                i = (i + 1) % self.capacity

            print(self.queue[i])


# Driver Code
q = Queue(6)
q.dequeue()  # Underflow condition

q.enqueue(12)
q.enqueue(14)
q.enqueue(16)
q.enqueue(18)
q.enqueue(20)

q.display()
q.dequeue()
q.dequeue()

q.display()

q.enqueue(22)
q.enqueue(24)
q.enqueue(26)
q.enqueue(28)  # Overflow condition
q.display()

Try It Yourself, Practicing the Code

Now that you've seen the code for implementing a queue, it's time to roll up your sleeves and try it out for yourself.๐Ÿช„

Putting Queues into Action ๐Ÿ› ๏ธ

Queues can be implemented using various data structures, but one common method is using an array. Take a look at this basic C/C++ code:

Queue implementation using c/c++ (Method 1).Here i had chosen c language

Stay Curious and Experiment! ๐ŸŒŸ

As we conclude our journey into the realm of queues, I encourage you to stay curious and experiment. Create your own queue implementations, explore different types of queues, and test their performance in various scenarios.

In our next session, we'll embark on another adventure, delving into more captivating data structures and algorithms that will expand your programming horizons. Get ready for more magic in the world of computer science and coding!

Remember, every line of code you write is a step forward in your journey to becoming a coding wizard. ๐Ÿช„๐Ÿ’ปโœจ

ย