0% found this document useful (0 votes)
36 views

Queue DS

The document discusses deque (double-ended queue), which allows insertion and deletion from both ends. It can be used as a stack, queue, or palindrome checker. There are two types - input restricted allows insertion at one end only, while output restricted allows deletion at one end only. Queues can be implemented using arrays or linked lists. Circular queues were introduced to avoid wasted space at the ends of arrays.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
36 views

Queue DS

The document discusses deque (double-ended queue), which allows insertion and deletion from both ends. It can be used as a stack, queue, or palindrome checker. There are two types - input restricted allows insertion at one end only, while output restricted allows deletion at one end only. Queues can be implemented using arrays or linked lists. Circular queues were introduced to avoid wasted space at the ends of arrays.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 29

Deque (or, Double Ended Queue)

In Deque or Double Ended Queue, insertion and deletion can be done from both ends
of the queue either from the front or rear.

It means that we can insert and delete elements from both front and rear ends of the
queue.

Deque can be used as a palindrome checker means that if we read the string from both
ends, then the string would be the same.

Deque can be used both as stack and queue as it allows the insertion and deletion
operations on both ends.

Deque can be considered as stack because stack follows the LIFO (Last In First Out)
principle in which insertion and deletion both can be performed only from one end. And
in deque, it is possible to perform both insertion and deletion from one end, and Deque
does not follow the FIFO principle.

The representation of the deque is shown in the below image -

To know more about the deque, you can click the link - https://www.javatpoint.com/ds-
deque

There are two types of deque that are discussed as follows -

o Input restricted deque - As the name implies, in input restricted queue, insertion
operation can be performed at only one end, while deletion can be performed
from both ends.

o Output restricted deque - As the name implies, in output restricted queue,


deletion operation can be performed at only one end, while insertion can be
performed from both ends.

Operations performed on queue


The fundamental operations that can be performed on queue are listed as follows -

o Enqueue: The Enqueue operation is used to insert the element at the rear end of the
queue. It returns void.
o Dequeue: It performs the deletion from the front-end of the queue. It also returns the
element which has been removed from the front-end. It returns an integer value.
o Peek: This is the third operation that returns the element, which is pointed by the front
pointer in the queue but does not delete it.
o Queue overflow (isfull): It shows the overflow condition when the queue is completely
full.
o Queue underflow (isempty): It shows the underflow condition when the Queue is
empty, i.e., no elements are in the Queue.

Ways to implement the queue


There are two ways of implementing the Queue:

o Implementation using array: The sequential allocation in a Queue can be implemented


using an array.

Array representation of Queue


We can easily represent queue by using linear arrays.

There are two variables i.e. front and rear, that are implemented in the case of every
queue. Front and rear variables point to the position from where insertions and
deletions are performed in a queue.

Initially, the value of front and queue is -1 which represents an empty queue.

Array representation of a queue containing 5 elements along with the respective values
of front and rear, is shown in the following figure.
The above figure shows the queue of characters forming the English word "HELLO".
Since, No deletion is performed in the queue till now,

therefore the value of front remains -1 .

However, the value of rear increases by one every time an insertion is performed in the
queue. After inserting an element into the queue shown in the above figure, the queue
will look something like following. The value of rear will become 5 while the value of
front remains same.
After deleting an element, the value of front will increase from -1 to 0. however, the
queue will look something like following.

Algorithm to insert any element in a queue


Algorithm to delete an element from the
queue
If, the value of front is -1 or value of front is greater than rear ,

write an underflow message and exit.

Otherwise, keep increasing the value of front and return the item stored at the front end
of the queue at each time.
Drawback of array implementation
The technique of creating a queue is easy, but there are some drawbacks of using this
technique to implement a queue.

o Memory wastage : The space of the array, which is used to store queue elements, can
never be reused to store the elements of that queue because the elements can only be
inserted at front end and the value of front might be so high so that, all the space before
that, can never be filled.
A queue of size 10 having 3 elements, is shown. The value of the front variable is 5,
therefore, we can not reinsert the values in the place of already deleted element before
the position of front. That much space of the array is wasted and can not be used in the
future (for this queue).

o Deciding the array size

On of the most common problem with array implementation is the size of the array
which requires to be declared in advance.

Due to the fact that, the queue can be extended at runtime depending upon the
problem, the extension in the array size is a time taking process and almost impossible
to be performed at runtime since a lot of reallocations take place.

Due to this reason, we can declare the array large enough so that we can store queue
elements as enough as possible but the main problem with this declaration is that, most
of the array slots (nearly half) can never be reused. It will again lead to memory wastage.

Linked List implementation of Queue


The storage requirement of linked representation of a queue with n elements is
o(n) while the time requirement for operations is o(1).

In a linked queue, each node of the queue consists of two parts i.e. data part and the
link part. Each element of the queue points to its immediate next element in the
memory.
In the linked queue, there are two pointers maintained in the memory i.e. front pointer
and rear pointer. The front pointer contains the address of the starting element of the
queue while the rear pointer contains the address of the last element of the queue.

Insertion and deletions are performed at rear and front end respectively. If front and
rear both are NULL, it indicates that the queue is empty.

The linked representation of queue is shown in the following figure.

Operation on Linked Queue


There are two basic operations which can be implemented on the linked queues. The
operations are Insertion and Deletion.

Insert operation
The insert operation append the queue by adding an element to the end of the queue.
The new element will be the last element of the queue.

Firstly, allocate the memory for the new node ptr by using the following statement.

1. Ptr = (struct node *) malloc (sizeof(struct node));

There can be the two scenario of inserting this new node ptr into the linked queue.

In the first scenario, we insert element into an empty queue. In this case, the
condition front = NULL becomes true.

Now, the new element will be added as the only element of the queue and the next
pointer of front and rear pointer both will point to NULL.
1. ptr -> data = item;
2. if(front == NULL)
3. {
4. front = ptr;
5. rear = ptr;
6. front -> next = NULL;
7. rear -> next = NULL;
8. }

In the second case,

the queue contains more than one element.

The condition front = NULL becomes false. In this scenario, we need to update the end
pointer rear so that the next pointer of rear will point to the new node ptr.

Since, this is a linked queue, hence we also need to make the rear pointer point to the
newly added node ptr.

We also need to make the next pointer of rear point to NULL.

1. rear -> next = ptr;


2. rear = ptr;
3. rear->next = NULL;

Deletion
Deletion operation removes the element that is first inserted among all the queue
elements.

Firstly, we need to check either the list is empty or not.


The condition front == NULL becomes true if the list is empty, in this case , we simply
write underflow on the console and make exit.

Otherwise, we will delete the element that is pointed by the pointer front.

For this purpose, copy the node pointed by the front pointer into the pointer ptr.

Now, shift the front pointer, point to its next node and free the node pointed by the
node ptr. This is done by using the following statements.

1. ptr = front;
2. front = front -> next;
3. free(ptr);

The algorithm and C function is given as follows.


Circular Queue

Why was the concept of the circular queue


introduced?
There was one limitation in the array implementation of Queue.

If the rear reaches to the end position of the Queue then there might be possibility that
some vacant spaces are left in the beginning which cannot be utilized. So, to overcome
such limitations, the concept of the circular queue was introduced.

As we can see in the above image, the rear is at the last position of the Queue and front
is pointing somewhere rather than the 0 th position.
In the above array, there are only two elements and other three positions are empty. The
rear is at the last position of the Queue; if we try to insert the element then it will show
that there are no empty spaces in the Queue.

There is one solution to avoid such wastage of memory space by shifting both the
elements at the left and adjust the front and rear end accordingly.

It is not a practically good approach because shifting all the elements will consume lots
of time.

The efficient approach to avoid the wastage of the memory is to use the circular queue
data structure.

What is a Circular Queue?


A circular queue is similar to a linear queue as it is also based on the FIFO (First In First
Out) principle except that the last position is connected to the first position in a circular
queue that forms a circle. It is also known as a Ring Buffer.

Operations on Circular Queue

o Front: It is used to get the front element from the Queue.


o Rear: It is used to get the rear element from the Queue.
o enQueue(value): This function is used to insert the new value in the Queue. The
new element is always inserted from the rear end.
o deQueue(): This function deletes an element from the Queue. The deletion in a
Queue always takes place from the front end.

Applications of Circular Queue


The circular Queue can be used in the following scenarios:

o Memory management: The circular queue provides memory management. As


we have already seen that in linear queue, the memory is not managed very
efficiently. But in case of a circular queue, the memory is managed efficiently by
placing the elements in a location which is unused.
o CPU Scheduling: The operating system also uses the circular queue to insert the
processes and then execute them.
o Traffic system: In a computer-control traffic system, traffic light is one of the
best examples of the circular queue. Each light of traffic light gets ON one by one
after every jinterval of time. Like red light gets ON for one minute then yellow
light for one minute and then green light. After green light, the red light gets ON.

Enqueue operation
The steps of enqueue operation are given below:

o First, we will check whether the Queue is full or not.


o Initially the front and rear are set to -1. When we insert the first element in a
Queue, front and rear both are set to 0.
o When we insert a new element, the rear gets incremented, i.e., rear=rear+1.

Scenarios for inserting an element


There are two scenarios in which queue is not full:

o If rear != max - 1, then rear will be incremented to mod(maxsize) and the new
value will be inserted at the rear end of the queue.
o If front != 0 and rear = max - 1, it means that queue is not full, then set the
value of rear to 0 and insert the new element there.

There are two cases in which the element cannot be inserted:

o When front ==0 && rear = max-1, which means that front is at the first position
of the Queue and rear is at the last position of the Queue.
o front== rear + 1;
Dequeue Operation
The steps of dequeue operation are given below:

o First, we check whether the Queue is empty or not. If the queue is empty, we
cannot perform the dequeue operation.
o When the element is deleted, the value of front gets decremented by 1.
o If there is only one element left which is to be deleted, then the front and rear are
reset to -1.
Let's understand the enqueue and dequeue operation through the diagrammatic
representation.
What is a priority queue?
A priority queue is an abstract data type that behaves similarly to the normal queue
except that each element has some priority, i.e., the element with the highest priority
would come first in a priority queue.

The priority of the elements in a priority queue will determine the order in which
elements are removed from the priority queue.
The priority queue supports only comparable elements, which means that the elements
are either arranged in an ascending or descending order.

For example, suppose we have some values like 1, 3, 4, 8, 14, 22 inserted in a priority
queue with an ordering imposed on the values is from least to the greatest. Therefore,
the 1 number would be having the highest priority while 22 will be having the lowest
priority.

Characteristics of a Priority queue


A priority queue is an extension of a queue that contains the following characteristics:

o Every element in a priority queue has some priority associated with it.
o An element with the higher priority will be deleted before the deletion of the
lesser priority.
o If two elements in a priority queue have the same priority, they will be arranged
using the FIFO principle.

We have a priority queue that contains the following values:

1, 3, 4, 8, 14, 22

All the values are arranged in ascending order. Now, we will observe how the priority
queue will look after performing the following operations:

o poll(): This function will remove the highest priority element from the priority
queue. In the above priority queue, the '1' element has the highest priority, so it
will be removed from the priority queue.
o add(2): This function will insert '2' element in a priority queue. As 2 is the
smallest element among all the numbers so it will obtain the highest priority.
o poll(): It will remove '2' element from the priority queue as it has the highest
priority queue.
o add(5): It will insert 5 element after 4 as 5 is larger than 4 and lesser than 8, so it
will obtain the third highest priority in a priority queue.

Types of Priority Queue


There are two types of priority queue:

o Ascending order priority queue: In ascending order priority queue, a lower


priority number is given as a higher priority in a priority. For example, we take the
numbers from 1 to 5 arranged in an ascending order like 1,2,3,4,5; therefore, the
smallest number, i.e., 1 is given as the highest priority in a priority queue.

o Descending order priority queue: In descending order priority queue, a higher


priority number is given as a higher priority in a priority. For example, we take the
numbers from 1 to 5 arranged in descending order like 5, 4, 3, 2, 1; therefore, the
largest number, i.e., 5 is given as the highest priority in a priority queue.
Representation of priority queue
Now, we will see how to represent the priority queue through a one-way list.

We will create the priority queue by using the list given below in which INFO list
contains the data elements, PRN list contains the priority numbers of each data element
available in the INFO list, and LINK basically contains the address of the next node.

Implementation of Priority Queue


The priority queue can be implemented in four ways that include

arrays,

linked list,

heap data structure and

binary search tree.

The heap data structure is the most efficient way of implementing the priority queue, so
we will implement the priority queue using a heap data structure.
Analysis of complexities using different implementations

Implementation add Remove peek

Linked list O(1) O(n) O(n)

Binary heap O(logn) O(logn) O(1)

Binary search tree O(logn) O(logn) O(1)

What is Heap?
A heap is a tree-based data structure that forms a complete binary tree, and satisfies the
heap property. If A is a parent node of B, then A is ordered with respect to the node B
for all nodes A and B in a heap.

It means that the value of the parent node could be more than or equal to the value of
the child node,

or the value of the parent node could be less than or equal to the value of the child
node. Therefore, we can say that there are two types of heaps:
o Max heap: The max heap is a heap in which the value of the parent node is
greater than the value of the child nodes.

o Min heap: The min heap is a heap in which the value of the parent node is less
than the value of the child nodes.
Both the heaps are the binary heap, as each has exactly two child nodes.

Priority Queue Operations


The common operations that we can perform on a priority queue are insertion, deletion
and peek. Let's see how we can maintain the heap data structure.

o Inserting the element in a priority queue (max heap)

If we insert an element in a priority queue, it will move to the empty slot by looking
from top to bottom and left to right.

If the element is not in a correct place then it is compared with the parent node; if it is
found out of order, elements are swapped. This process continues until the element is
placed in a correct position.
o Removing the minimum element from the priority queue

As we know that in a max heap, the maximum element is the root node. When we
remove the root node, it creates an empty slot. The last inserted element will be added
in this empty slot. Then, this element is compared with the child nodes, i.e., left-child
and right child, and swap with the smaller of the two. It keeps moving down the tree
until the heap property is restored.
Applications of Priority queue
The following are the applications of the priority queue:

o It is used in the Dijkstra's shortest path algorithm.


o It is used in prim's algorithm
o It is used in data compression techniques like Huffman code.
o It is used in heap sort.
o It is also used in operating system like priority scheduling, load balancing and
interrupt handling.

You might also like