Queue
A Queue is a linear data structure which follows a particular order in which the operations are performed. The order is First in First out (FIFO).
A good example for Queue is, any queue of consumers for resource
where the consumer that came first is served first. The main difference between
the stack and queue is in removing. In a stack, we remove the most recently
added item to the stack; in a queue, we remove the least recently added item to
the queue.
Operations on Queue
The following are the basic operations performed on queue:
Enqueue: Adds an
item to the queue. If the queue is full, then it is said to be an Overflow condition.
Dequeue: Removes
an item from the queue. The items are popped in the same order in which they
are pushed. If the queue is empty, then it is said to be an Underflow condition.
Front: Get the
front element from queue.
Rear: Get the
rear element from queue.
Queue Implementation
The Queue can be implemented using following ways, such as:
Array
Implementation of Queue
The Queue can be implemented using Array. For this, we need to
keep track of two indices front and rear.
We Enqueue the item at the rear and we Dequeue the item at the front. If
we simply increment the front and rear indices in the Array, then there may be
problems such as it may reach end of the array. The solution to this problem is
to increase front and rear in circular manner.
In Queue, insertion and deletion happens at opposite ends, so implementation of Queue using arrays is not as simple as Stack. To implement a queue using array, create an array arr of size n and take two variables front and rear both of which will be initialized to 0 which means the queue is currently empty. The variable rear is the index value which stores the rear index of the array whereas the variable front stores the index of the first element of the array. Following are the some of the implementations of Queue operations such as:
From the above figure, the queue is implemented using Array. The
queue has an array of integer values. In the second figure, Enqueue a data at
the rear end and the value of rear is incremented by 1. In the third figure,
Dequeue a data from the front and all the values are shifted from rear to front
by 1 position.
The following is the C code for the implementation of Queue using Array:
#include<stdio.h> #include<stdlib.h> #define CAPACITY 100 #define INT_MIN -1 int queue[CAPACITY]; unsigned int rear = 0; unsigned int front = 0; unsigned int size = 0; //Check the overflow condition int isFull() { return(size==CAPACITY); } //Check the underflow condition int isEmpty() { return(size==0); } //Add element at rear of the queue int enqueue(int data) { if(isFull()) { return 0; } if(rear > 0 || !isEmpty()) rear = rear+1; size++; printf("=====Rear value is %d", rear); queue[rear] = data; return 1; } //Delete an element from front of the queue int dequeue() { int data; if(isEmpty()) { return INT_MIN; } data = queue[front]; size--; for(int i=0; i<size; i++) { queue[i] = queue[i+1]; } rear--; return data; } //Get the front element from the Queue int getFront() { return(isEmpty())?INT_MIN:queue[front]; } //Get the rear element from the Queue int getRear() { return(isEmpty())?INT_MIN:queue[rear]; } //Print all the elements at the Queue int printQueue() { if(isEmpty()) { return INT_MIN; } for (int i=0; i<size; i++) { printf("%d\t", queue[i]); } return 1; } int main() { int ch, data; while(1) { printf("1.Enqueue\t2.Dequeue\t3.Print the Queue\n"); printf("4.GetFront\t5.GetRear\t0.Exit\n"); scanf("%d", &ch); switch(ch) { case 1: printf("Enter the data to enqueue : "); scanf("%d", &data); if(enqueue(data)) printf("Element is added to the queue"); else printf("Queue is full"); break; case 2: data = dequeue(); if(data == INT_MIN) printf("Queue is empty"); else printf("Data dequeued is %d ", data); break; case 3: if(printQueue() == INT_MIN) printf("Queue is empty"); break; case 4: data = getFront(); if(data == INT_MIN) printf("Queue is empty"); else printf("The front data is %d", data); break; case 5: data = getRear(); if(data == INT_MIN) printf("Queue is empty"); else printf("The rear data is %d", data); break; case 0: printf("Exiting from the loop"); exit(0); default: printf("Invalid choice, please input b/w (0-5)."); break; } printf("\n"); } }
Output
1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 1 Enter the data to enqueue : 2 =====Rear value is 0Element is added to the queue 1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 1 Enter the data to enqueue : 4 =====Rear value is 1Element is added to the queue 1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 3 2 4 1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 4 The front data is 2 1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 5 The rear data is 4 1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 2 Data dequeued is 2 1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 2 Data dequeued is 4 1.Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit 2 Queue is empty 1. Enqueue 2.Dequeue 3.Print the Queue 4.GetFront 5.GetRear 0.Exit
The above code gives detail implementation of queue using array. The
size of the queue is incremented when the data is added to the rear of the
queue and the size of the queue is decremented when the data is removed from
the front end and all the data in the queue is shifted from rear to front by
one position. The CAPACITY is the maximum limit of the Queue. When the Queue is empty, then the size value
will be -1.
Linked
List implementation of Queue
The Queue is also implemented using Linked list. In this
implementation, a Queue data structure maintains two pointers namely front and rear. The front points to the first item of the queue and rear
points to the last item of the queue.
The following are the two important implementations of Queue
namely,
enQueue()– This
operation add a new node after rear and moves the rear pointer to the next
node.
deQueue() – This
operation removes the front node and move the front pointer to the next node.
The following figure represents the Linked List implementation of Queue:
#include <stdio.h> #include <stdlib.h> // A linked list (LL) node to store a queue entry struct QNode { int key; struct QNode* next; }; // The queue, front stores the front node of LL and rear stores the // last node of LL struct Queue { struct QNode *front, *rear; }; // To create a new linked list node. struct QNode* newNode(int k) { struct QNode* temp = (struct QNode*)malloc(sizeof(struct QNode)); temp->key = k; temp->next = NULL; return temp; } // To create a empty Queue struct Queue* createQueue() { struct Queue* q = (struct Queue*)malloc(sizeof(struct Queue)); q->front = q->rear = NULL; return q; } // To add a key k to q void enQueue(struct Queue* q, int k) { // Create a new List node struct QNode* temp = newNode(k); // If queue is empty, then new node is front and rear both if (q->rear == NULL) { q->front = q->rear = temp; return; } // Add the new node at the end of queue and change rear q->rear->next = temp; q->rear = temp; } // Function to remove a key from given queue q void deQueue(struct Queue* q) { // If queue is empty, return NULL. if (q->front == NULL) return NULL; // Store previous front and move front one node ahead struct QNode* temp = q->front; printf("Dequeued element is %d\n", temp->key); q->front = q->front->next; free(temp); // If front becomes NULL, then change rear also as NULL if (q->front == NULL) q->rear = NULL; } // Driver Program to test anove functions int main() { struct Queue* q = createQueue(); enQueue(q, 15); enQueue(q, 25); deQueue(q); deQueue(q); enQueue(q, 35); enQueue(q, 45); enQueue(q, 55); deQueue(q); return 0; }
Output
Dequeued element is 15 Dequeued element is 25 Dequeued element is 35
Applications of Queue
Queue is used when the things are not processed immediately, but will be processed in First come First order. The following are the scenarios; the property of Queue is used,