Understanding Queue Data Structures
Understanding Queue Data Structures
QUEUES
5.1 Introduction
5.2 Representation - Static & Dynamic
5.3 Primitive Operations on Queue
5.4 Circular queue, priority queue
5.5 Concept of doubly ended queue
INTRODUCTION :
⮚ Queue is similar to the queue which is usually seen in our day today life like a queue of
people on a railway station.
⮚ Queues are also used in computers for maintaining job queue.
In multiprogramming system there are many jobs present in the system. These jobs are
to be allocated to the CPU one at a time only on context-switching basis. How should the operating
system decide as to which job should get the CPU turn? For doing this jobs job pool is maintained
in the form of queue. The queue can be maintained according to first come first serve basis or
according to the priority i.e jobs with highest priority is first in the queue and job with lowest
priority is last in queue. The job is dispatched from the front of queue and given to the CPU and
whenever a new job arrives it is placed at the rear of the queue.
⮚ DEFINITION :
A queue is an ordered collection of items from which items may be deleted from (or
removed from ) one end called the front and into which items may be inserted at the other end
called rear.
⮚ The elements are added and deleted in FIFO ( first in first out) manner
-1
A B C
Front rear
A B C D
-1
Front rear
An element can be deleted only from the front. Thus A will be the front to be removed.
B C D
Front rear
Elements are added and removed from the Elements are added and removed from
same end. different ends.
The basic operations are PUSH and POP The basic operations are ADD and
DELETE.
Top moves in both directions. Hence vacant Front and rear move in one direction only.
positions are reused.
No concept of circular stack The concept of a circular queue exists.
We cannot have a priority stack We have a priority queue.
⮚ TYPES OF QUEUE
1) linear:
In this queue the elements are arranged into a sequential manner, Such that
front position is always less than or equal to the rear position. When an element is
added, rear is incremented and when an element is removed front is advanced. Thus
front always follows rear.
Example:
A B
-1 C
Front rear
2) Circular queue:
In this queue, the elements are arranged in a sequential manner but can logically be
regarded as circularly arranged
C D
B
A
Example: (rear)
CC
Empty position
(front)
#include<stdio.h>
#define MAX 5
//create the queue
Struct queue
{
int Q[MAX];
int front,rear;
};
typedef struct queue QUEUE;
QUEUE *front=NULL,*rear=NULL;
main()
{
int ch,data;
while(1)
{
printf("\n \t 1 : Add");
printf("\n \t 2 : Delete");
printf("\n \t 3 : Peek");
printf("\n \t 4 : Display");
printf("\n \t 5 : Exit");
printf("\n \t Enter UR choice : ");
scanf("%d",&ch);
switch(ch)
{
case 1 :
printf("\nEnter the data to be added-> ");
scanf("%d",&data);
addq(data);
break;
case 2:
if(isemptyq())
printf("\nqueue is empty");
else
printf("\ndeleted data is %d",deleteq());
break;
case 3:
if(isemptyq())
printf("\nqueue is empty");
else
printf("\nFront element is %d",peek());
break;
case 4:
if(isemptyq())
printf("\nqueue is empty");
else
displayq();
break;
case 5:
exit(1);
}
}
}
int isemptyq()
{
if (front==NULL)
return 1;
else
return 0;
}
int peek()
{
return(front->data);
}
int deleteq()
{
QUEUE *ptr1,*ptr=NULL;
int val;
ptr=front;
val=ptr->data;
if(front->next!=NULL)
{
front=front->next;
}
else
{
front=NULL;
rear=NULL;
}
free(ptr);
return(val);
}
void displayq()
{
QUEUE *ptr;
printf("\n \t Ur Queue Lokks Like...\n ");
for(ptr=front;ptr->next!=NULL;ptr=ptr->next)
{
printf("%d-> ",ptr->data);
}
printf("%d",ptr->data);
}
/*
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 1
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 1
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 1
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 4
Front element is 1
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 4
deleted data is 1
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 2
deleted data is 2
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 2
deleted data is 3
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 2
queue is empty
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 3
queue is empty
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 4
queue is empty
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 5
*/
● Applications of queue:
1) Various features of operating system are implemented using a queue
- Scheduling of processes (round robin algorithm)
- Spooling (to maintain a queue of jobs to be printed)
- A queue of client process waiting to receive the service from the server process.
2) Queues are used in simulation.
E.g. In airport simulation, to keep the track of problems like number of plane
processed, the average time spent waiting etc. queue are used.
3) Multiple print jobs given to a printer are organized in the FIFO number in a print
queue and given to the printer.
4) In batch programming multiple jobs are combined into a batch and the first program is
executed next and so on in a sequential manner.
● Circular queue
Disadvantage of linear queue
Consider queue with maximum size 5. Initially the queue is empty i.e. front and rear
are at -1. After the elements ABCD and E are added, the queue will look like
-1 A B C D E
C
Front rear
If we remove two elements from the queue
C D E
C
Front rear
We have two vacant positions at the beginning of the queue but we cannot add new elements
there since rear has reached MAX-1. Which is the queue full condition? Thus even if elements are
removed from the queue, new elements cannot take their positions.
The simple solution to the above problem is that whenever rear gets to the end of the array, it
wrapped around to the beginning. Now array can be thought of as a circle. The first position
follows the last element.
A B C D E
C
Next of A is E
C D E
C
Front rear
Now we can insert element at the beginning by bringing rear to the first position in the queue.
F C D E
C
Rear front
A peculiar situation arises when the queue is full.
In the above example if another element G is added to the queue, it will look like:
F G C D E
C
Rear , front
i.e. rear and front coincide. But rear and front coincide even when queue is empty. Hence there is
an ambiguity. Rear==front cannot be used for both i.e. to check for an empty queue as well as the
condition for a full queue. Hence some method of resolving this problem is needed. We shall keep
the rear==front condition as a check for an empty queue since initially both are initialized to the
same value. Thus we need another method to check for a full queue.
if(q->rear==-1)
{
q->rear=q->front=0;
q->Q[q->rear]=data;
}
else
{
q->rear=(q->rear+1)%MAX;
q->Q[q->rear]=data;
}
}
for(i=q->front;i!=q->rear;i=(i+1)%MAX)
printf("%d\t",q->Q[i]);
printf("%d\t",q->Q[i]);
}
#include<stdio.h>
#include<stdlib.h>
#include"stcqueue.h"
main()
{
QUEUE q;
int ch,data;
initqueue(&q);
while(1)
{
printf("\n\nMain Menu");
printf("\n1 : ADD");
printf("\n2 : DELETE");
printf("\n3 : DISPLAY");
printf("\n4 : EXIT");
printf("\nEnter the choice=> ");
scanf("%d",&ch);
switch(ch)
{
case 1:
if (isfullq(&q))
printf("\nqueue is full");
else
{
printf("\nEnter the data to be added-> ");
scanf("%d",&data);
addq(&q,data);
}
break;
case 2:
if(isemptyq(&q))
printf("\nqueue is empty");
else
printf("\ndeleted data is %d",deleteq(&q));
break;
case 3:
if(isemptyq(&q))
printf("\nqueue is empty");
else
displayq(&q);
break;
case 4:
exit(1);
}
}
}
Queue created
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 1
Enter the data to be added-> 12
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 1
Enter the data to be added-> 2
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 1
Enter the data to be added-> 14
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 3
12 2 14
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 2
deleted data is 12
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 2
deleted data is 2
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 2
deleted data is 14
Main Menu
1 : ADD
2 : DELETE
3 : DISPLAY
4 : EXIT
Enter the choice=> 3
queue is empty
Data Structures:
1. The code defines a constant MAX with a value of 5, which represents the maximum size of the
queue.
2. It defines a struct named queue with members front, rear, and an array Q to store the elements
in the queue.
3. A typedef statement creates an alias QUEUE for the struct queue.
Global Variables:
● There's a global variable newrear, which is used to check if the queue is full.
Queue Initialization:
● The initqueue function initializes the queue. It sets all elements of the Q array to 0, and both the
front and rear are set to -1, indicating an empty queue. It also prints "Queue created."
Queue Operations:
Main Function:
● In the main function, an instance of the QUEUE struct is created, and it is initialized using
initqueue.
● The main menu is displayed in a loop, and the user can choose from four options:
● Option 1 (ADD): Calls addq to add an element to the queue if it's not full.
● Option 2 (DELETE): Calls deleteq to remove and display an element from the queue if
it's not empty.
● Option 3 (DISPLAY): Calls displayq to display the elements in the queue if it's not
empty.
● Option 4 (EXIT): Exits the program.
Dry & Run
1. initqueue function is called, and it prints "Queue created."
2. The program enters a menu loop where you can choose options.
3. You choose option 1 (ADD) and input the value 12. The addq function adds 12 to the queue.
4. You choose option 1 (ADD) again and input the value 2. The addq function adds 2 to the queue.
5. You choose option 1 (ADD) once more and input the value 14. The addq function adds 14 to the
queue.
6. You choose option 3 (DISPLAY), and the displayq function prints the contents of the queue:
"12 2 14."
7. You choose option 2 (DELETE), and the deleteq function removes and prints "12" from the
queue.
8. You choose option 2 (DELETE) again, and the deleteq function removes and prints "2" from the
queue.
9. You choose option 2 (DELETE) one more time, and the deleteq function removes and prints
"14" from the queue.
10. You choose option 3 (DISPLAY) again, and the displayq function shows that the queue is
empty, as it prints "queue is empty."
11. The menu loop continues, allowing you to perform more operations.
It appears that the code is working correctly, managing the queue, adding, deleting, and
displaying elements while checking for empty and full conditions.
struct queue
{
int data;
struct queue *next;
};
int peek()
{
return(front->data);
}
int deleteq()
{
QUEUE *ptr1,*ptr=NULL;
int val;
ptr=front;
val=ptr->data;
if(front->next!=front)
{
front=front->next;
rear->next=front;
}
else
{
front=NULL;
rear=NULL;
}
free(ptr);
return(val);
}
void displayq()
{
QUEUE *ptr;
printf("\n \t Ur Queue Lokks Like...\n ");
for(ptr=front;ptr->next!=front;ptr=ptr->next)
{
printf("%d-> ",ptr->data);
}
printf("%d",ptr->data);
}
#include<stdio.h>
#include<stdlib.h>
#include"dycqueue.h"
main()
{
int ch,data;
while(1)
{
printf("\n \t 1 : Add");
printf("\n \t 2 : Delete");
printf("\n \t 3 : Peek");
printf("\n \t 4 : Display");
printf("\n \t 5 : Exit");
printf("\n \t Enter UR choice : ");
scanf("%d",&ch);
switch(ch)
{
case 1 :
printf("\nEnter the data to be addded: ");
scanf("%d",&data);
addq(data);
break;
case 2:
if(isemptyq())
printf("\nqueue is empty");
else
printf("\ndeleted data is %d",deleteq());
break;
case 3:
if(isemptyq())
printf("\nqueue is empty");
else
printf("\nFront element is %d",peek());
break;
case 4:
if(isemptyq())
printf("\nqueue is empty");
else
displayq();
break;
case 5:
exit(1);
}
}
}
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 1
Enter the data to be addded: 6
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 1
Enter the data to be addded: 9
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice :
1
Enter the data to be addded: 5
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 4
Ur Queue Lokks Like...
6-> 9-> 5
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 3
Front element is 6
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 2
deleted data is 6
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 2
deleted data is 9
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 2
deleted data is 5
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice : 2
queue is empty
1 : Add
2 : Delete
3 : Peek
4 : Display
5 : Exit
Enter UR choice :
The provided C code implements a dynamic circular queue using a linked list data structure. This
code allows you to add elements to the queue, delete elements from the queue, peek at the front
element, display the queue, and exit the program.
Here's a breakdown of the code and a dry run based on your input:
Data Structures:
● The code defines a structure named queue with two members: data to store the data and next to
point to the next element in the queue.
Global Variables:
● Two global pointers, rear and front, are initialized as NULL. These pointers are used to keep
track of the rear and front of the circular queue.
Queue Operations:
● isemptyq checks if the queue is empty by checking if front is NULL.
● alloc allocates memory for a new element in the queue and initializes it with the given data.
● peek returns the data stored in the front element of the queue.
● addq adds an element to the queue by allocating memory for it and updating front and rear
pointers accordingly. It handles both empty and non-empty queue cases.
● deleteq removes the front element from the queue and returns its data. It also updates front and
rear pointers accordingly. It handles both single-element and multiple-element cases.
● displayq displays the elements of the queue from front to rear.
Main Function:
● The main function contains a menu-driven loop allowing the user to perform queue operations.
● You can add elements to the queue (Option 1), delete elements (Option 2), peek at the front
element (Option 3), display the queue (Option 4), or exit the program (Option 5).
Dry Run:
1. You choose option 1 (Add) and add the value 6 to the queue.
2. You choose option 1 (Add) again and add the value 9 to the queue.
3. You choose option 1 (Add) once more and add the value 5 to the queue.
4. You choose option 4 (Display), and the queue is displayed: "6 -> 9 -> 5."
5. You choose option 3 (Peek), and it displays "Front element is 6."
6. You choose option 2 (Delete), and it deletes the front element (6) and displays it.
7. You choose option 2 (Delete) again, and it deletes the front element (9) and displays it.
8. You choose option 2 (Delete) one more time, and it deletes the last element (5) and displays it.
9. You choose option 2 (Delete) again, and it informs you that the queue is empty.
10. You can continue to perform more operations or exit the program.
The code appears to work as expected, correctly managing the dynamic circular queue and
handling various queue conditions.
PRIORITY QUEUE:
It is an ordered list of homogeneous elements. In normal queue Service is provided on first in first
out. In Priority queue service is not provided on the basis of FIFO rather than each element has a
priority based on the urgency of need.
● An element with higher priority is processed before other elements with lower priority.
� Circular array
As the services must be provided to an element having highest priority, there could be a choice
between
a) List is always maintained sorted on priority of elements with the highest priority element at
the front. Here deletion is trivial but insertion is complicated as the elements must be
inserted at the correct place depending on its priority.
b) List is maintained in the FIFO form but the service is provided by selecting the element
with highest priority. Deletion is difficult as the entire queue must be traversed to locate the
element with highest priority. Here insertion is trivial
● DEQUEUE:-
⮚ It is general representation of both stack and queue and can be used as stack and queue
⮚ A dequeue is a linear list in which insertion as well as deletion can be carried out either at
the rear and or at the front end, but not in the middle.
⮚ In practice , it becomes necessary to fix the type of operation to be performed on front and
rear end.
⮚ The two ends are called left and right respectively. thus four possible operations on a
dequeue.
1) Insert left
2) Insert right
3) Delete left
4) Delete right
● Types of Dequeue
a) Input restricted Dequeue:-
It is a queue which allows insertion at one end of the list but allows deletion at both ends of
the lists.
i.e. The following operations are possible:-
- Insertion of an element at the rear.
- Deletion of an element from front.
- Deletion of an element from rear.
b) Output restricted dequeue:-
It is a Dequeue which allows deletion at one end of the list, but allows insertion at both ends
of the list.
i.e. The following operations are possible in an output restricted dequeue.
- Deletion of an element from front end
- Insertion of an element at the rear.
- Insertion of an element at the front.
● Multiple queues: In MLQ scheduling, processes are divided into multiple queues based
on their priority, with each queue having a different priority level. Higher-priority
processes are placed in queues with higher priority levels, while lower-priority
processes are placed in queues with lower priority levels.
● Priorities assigned: Priorities are assigned to processes based on their type,
characteristics, and importance. For example, interactive processes like user
input/output may have a higher priority than batch processes like file backups.
● Preemption: Preemption is allowed in MLQ scheduling, which means a higher priority
process can preempt a lower priority process, and the CPU is allocated to the higher
priority process. This helps ensure that high-priority processes are executed in a
timely manner.
● Scheduling algorithm: Different scheduling algorithms can be used for each queue,
depending on the requirements of the processes in that queue. For example, Round
Robin scheduling may be used for interactive processes, while First Come First Serve
scheduling may be used for batch processes.
● Feedback mechanism: A feedback mechanism can be implemented to adjust the
priority of a process based on its behavior over time. For example, if an interactive
process has been waiting in a lower-priority queue for a long time, its priority may be
increased to ensure it is executed in a timely manner.
● Efficient allocation of CPU time: MLQ scheduling ensures that processes with higher
priority levels are executed in a timely manner, while still allowing lower priority
processes to execute when the CPU is idle.
● Fairness: MLQ scheduling provides a fair allocation of CPU time to different types of
processes, based on their priority and requirements.
● Customizable: MLQ scheduling can be customized to meet the specific requirements
of different types of processes.
Advantages of Multilevel Queue CPU Scheduling:
● Low scheduling overhead: Since processes are permanently assigned to their
respective queues, the overhead of scheduling is low, as the scheduler only needs to
select the appropriate queue for execution.
● Efficient allocation of CPU time: The scheduling algorithm ensures that processes
with higher priority levels are executed in a timely manner, while still allowing lower
priority processes to execute when the CPU is idle. This ensures optimal utilization of
CPU time.
● Fairness: The scheduling algorithm provides a fair allocation of CPU time to different
types of processes, based on their priority and requirements.
● Customizable: The scheduling algorithm can be customized to meet the specific
requirements of different types of processes. Different scheduling algorithms can be
used for each queue, depending on the requirements of the processes in that queue.
● Prioritization: Priorities are assigned to processes based on their type, characteristics,
and importance, which ensures that important processes are executed in a timely
manner.
● Preemption: Preemption is allowed in Multilevel Queue Scheduling, which means that
higher-priority processes can preempt lower-priority processes, and the CPU is
allocated to the higher-priority process. This helps ensure that high-priority processes
are executed in a timely manner.
Disadvantages of Multilevel Queue CPU Scheduling:
● Some processes may starve for CPU if some higher priority queues are never becoming
empty.
● It is inflexible in nature.
● There may be added complexity in implementing and maintaining multiple queues and
scheduling algorithms.
Ready Queue is divided into separate queues for each class of processes. For
example, let us take three different types of processes System processes, Interactive
processes, and Batch Processes. All three processes have their own queue. Now, look
at the below figure.
Priority of queue 1 is greater than queue 2. queue 1 uses Round Robin (Time
Quantum = 2) and queue 2 uses FCFS.
Below is the Gantt chart of the problem:
Working:
● At starting, both queues have process so process in queue 1 (P1, P2) runs first
(because of higher priority) in the round-robin fashion and completes after 7 units
● Then process in queue 2 (P3) starts running (as there is no process in queue 1) but
while it is running P4 comes in queue 1 and interrupts P3 and start running for 5
seconds and
● After its completion P3 takes the CPU and completes its execution.