Home
Learn
Practice
Contests
Rankings
Log In
Sign Up
Log In
Sign Up
Forgot Password ?
New password will be sent to following email id
Tutorial
Problems
Subtopics
Stack
Queue
Basic Data Structures
( Queue )
<h1>Queue</h1> Queue is a simple data structure used for storing data. In queue, the order in which the data arrives is important. A common example of queue is movie theater ticket counter, the first person who stands in front of ticket window take ticket first and remove from line and new person always stand in line from end. The first person entering the queue is the first one to go out.<br/><br/> <i>Queue is an ordered list in which insertion and deletion are done at different ends. End from which element is inserted is called <b>REAR or BACK</b> and end from which element is removed is called <b>FRONT</b>. The first element inserted is the first one to be removed. Hence it is called FIFO(first in first out) or LILO(last in last out)</i>. <br/> <hr/> <h3><i>Operations</i></h3> <br/> <b>1. Push</b><br/> When an element is inserted in the queue, it is added at rear or back end. This operation is known as push.<br/> <img src='https://s27.postimg.org/my0lcneib/image.jpg'><br> <img src='https://s24.postimg.org/4gd3kk0f9/image.jpg'><br> <img src='https://s28.postimg.org/5tn6owf65/image.jpg'><br> <b>2. Pop</b><br/> An element is removed from the front end of queue. (Element which was inserted earliest in comparison to all the elements present in the queue) This operation is called as pop.<br/> <img src='https://s29.postimg.org/56aq9tj8n/qp1.jpg'><br> <img src='https://s23.postimg.org/4g1pf2nln/qp2.jpg'><br> <img src='https://s29.postimg.org/xcw0lmwdz/qp3.jpg'><br> <hr/> <h3><i>Queue ADT</i></h3> Recall that an Abstract Data Type is defined as "class of objects whose logical behavior is defined by a set of values and a set of operations". i.e. an ADT consists of 2 parts - <ul> <li>Declaration of data</li> <li>Declaration of operations</li> </ul> <br/> <b>Main queue operations :</b> <ul> <li><b>void Push(data)</b>: Inserts data on the back or rear end of queue.</li> <li><b>void Pop()</b>: Removes data from the front end of queue.</li> </ul> <br/> <b>Auxiliary queue operations :</b> <ul> <li><b>Front()</b>: Returns the element present at the front end of queue without removing it.</li> <li><b>int Size()</b>: Returns the number of elements stored in queue.</li> <li><b>bool IsEmptyQueue()</b>: Returns true if queue is empty.</li> <li><b>bool IsFullQueue()</b>: Returns true if queue is full.</li> </ul> <br/> <hr/> <h3><i>Exceptions in Queue</i></h3> <ul> <li><b>Underflow</b>: Trying to access an element from an empty queue results in an underflow condition.</li> <li><b>Overflow</b>: Trying to push an element to a queue which has reached its capacity is called overflow.</li> </ul><br/> <hr/> <h3><i>Applications of Queue </i></h3> <ul> <li>Serving requests on a single shared resource, like a printer, CPU task scheduling etc.</li> <li>In real life, Call Center phone systems will use Queues, to hold people calling them in an order, until a service representative is free.</li> <li>Handling of interrupts in real-time systems. The interrupts are handled in the same order as they arrive, First come first served.</li> </ul> <br/><hr/> <h3><i>Simple Array Implementation</i></h3> In this method, we store the queue elements in a simple array, and keep a variable to maintain the front and rear end of queue.<br/> Elements are always added and removed in the left to right direction.<br/> Initially the rear variable is set to -1 and front variable is set to 0 and whenever we add any element to queue, we increase the rear variable. Similarly on poping an element, we increase the top variable.<br/> <pre><code>#include <bits/stdc++.h> using namespace std; struct arrayQueue { int frontIndex; int rearIndex; int capacity; int *arr; arrayQueue(int size) { this->rearIndex= -1; this->frontIndex= 0; this->capacity = size; this->arr = (int*) calloc(size, sizeof(int)); } bool isEmptyQueue() { return this->rearIndex < this->frontIndex; } bool isFullQueue() { return this->rearIndex == this->capacity - 1; } void push(int data) { if(isFullQueue()) printf("Queue Overflow!!\n"); else this->arr[++this->rearIndex] = data; } void pop() { if(isEmptyQueue()) printf("Queue Underflow!!\n"); else ++this->frontIndex; } int front() { if(isEmptyQueue()) { printf("Queue is Empty!!\n"); return -1; } return this->arr[this->frontIndex]; } int size() { return this->rearIndex - this->frontIndex + 1; } }; int main() { arrayQueue qu(10); //creates a queue of size 10 qu.push(4); // queue : 4 qu.push(1); // queue : 4 1 qu.pop(); // queue : 1 qu.push(3); // queue : 1 3 qu.push(5); // queue : 1 3 5 qu.push(4); // queue : 1 3 5 4 qu.pop(); // queue : 3 5 4 qu.push(2); // queue : 3 5 4 2 qu.pop(); // queue : 5 4 2 qu.pop(); // queue : 4 2 qu.pop(); // queue : 2 qu.pop(); // queue : qu.pop(); // This will cause queue underflow return 0; } </code></pre><br/> Following is the complexity analysis for above approach.<br/> <ul> <li>Space Complexity: O(n)</li> <li>Time Complexity for each push() operation: O(1)</li> <li>Time Complexity for each pop() operation: O(1)</li> <li>Time Complexity for each size() operation: O(1)</li> </ul> <br/> <b>Limitation</b>: This approach suffers from the limitation that the maximum size of the queue must be defined in prior and cannot be changed. Trying to push a new element into a full queue causes an implementation-specific exception.<br/>