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

Linear and Circular Queue Notes

Uploaded by

Mallika Thogaru
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
78 views

Linear and Circular Queue Notes

Uploaded by

Mallika Thogaru
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

UNIT-III

QUEUES
Queue is a linear data structure in which data inserted into one end and deleted from another
end. This structure follows the First In, First Out (FIFO) principle, meaning the first element
that is inserted will be the first one to be removed.
The process of adding an element into a queue is known as the enqueue operation, while the
process of removing an element is known as the dequeue operation. A Queue maintains two
pointers - the front pointer points to the first inserted element, while the rear pointer points to
the last inserted element.

Comparison between Stack and Queue:


Parameter Stack Data Structure Queue Data Structure

Design A Stack is a linear data structure where A Queue is also a linear data structure, but
removal and insertion occur at the removal and insertion happen at different
same end. ends.

Principle A Stack follows the Last In, First Out A Queue follows the First In, First Out (FIFO)
(LIFO) principle, meaning the most principle, meaning the earliest inserted
recently inserted element is removed element is removed first.
first.

Pointers A Stack uses a single pointer, the top, A Queue uses two pointers, the front and
to keep track of the most recently the rear, to keep track of the first and last
added element. inserted elements respectively.

Operations A Stack uses push and pop operations A Queue


for insertion and deletion respectively. uses enqueue and dequeue operations for
insertion and deletion respectively.

Structure In a Stack, both insertion and deletion In a Queue, insertion happens at the rear end
happen at the same end, known as the and deletion happens at the front end.
top.

Full A Stack is considered full when top A Queue is considered full when rear equals
Condition equals max-1. max-1.
Check

Empty A Stack is considered empty when top A Queue is considered empty when front
Condition equals -1. equals rear+1 or front equals -1.
Check

Variants A Stack does not have any variants. A Queue has three variants - circular queue,
priority queue, and double-ended queue.
Queue ADT
The following operations make a queue an ADT. Insertions and deletions in the queue must
follow the FIFO scheme.
Main Queue Operations
• EnQueue(int data): Inserts an element at the end of the queue
• int DeQueue(): Removes and returns the element at the front of the queue
Auxiliary Queue Operations
• int Front(): Returns the element at the front without removing it.
• int QueueSize(): Returns the number of elements stored in the queue
• int IsEmptyQueueQ: Indicates whether no elements are stored in the queue or not.

Operations on QUEUE:
A queue is an object or more specifically an abstract data structure (ADT) that allows the
following operations:
• Enqueue or insertion: which inserts an element at the end of the queue.
• Dequeue or deletion: which deletes an element at the start of the queue.

Queue operations work as follows:


1. Two pointers called FRONT and REAR are used to keep track of the first and last elements
in the queue.
2. When initializing the queue, we set the value of FRONT and REAR to 0.
3. On enqueing an element, we increase the value of REAR index and place the new element
in the position pointed to by REAR.
4. On dequeueing an element, we return the value pointed to by FRONT and increase the
FRONT index.
5. Before enqueing, we check if queue is already full.
6. Before dequeuing, we check if queue is already empty.
7. When enqueing the first element, we set the value of FRONT to 1.
8. When dequeing the last element, we reset the values of FRONT and REAR to 0.

Representation of Queue (or) Implementation of Queue:


The queue can be represented in two ways:
1. Queue using Array
2. Queue using Linked List

1.Queue using Array:


Let us consider a queue, which can hold maximum of five elements. Initially the queue is empty

Now, insert 11 to the queue. Then queue status will be:


Next, insert 22 to the queue. Then the queue status is:

Again, insert another element 33 to the queue. The status of the queue is:

Now, delete an element. The element deleted is the element at the front of the queue.So the
status of the queue is:

Again, delete an element. The element to be deleted is always pointed to by the FRONT pointer.
So, 22 is deleted. The queue status is as follows:

Now, insert new elements 44 and 55 into the queue. The queue status is: 18

Next insert another element, say 66 to the queue. We cannot insert 66 to the queue as the rear
crossed the maximum size of the queue (i.e., 5). There will be queue full signal. The queue
status is as follows:
Now it is not possible to insert an element 66 even though there are two vacant positions in the
linear queue. To overcome this problem the elements of the queue are to be shifted towards the
beginning of the queue so that it creates vacant position at the rear end. Then the FRONT and
REAR are to be adjusted properly. The element 66 can be inserted at the rear end. After this
operation, the queue status is as follows:

This difficulty can overcome if we treat queue position with index 0 as a position that comes
after position with index 4 i.e., we treat the queue as a circular queue.

1. Algorithm for Insertion in a Linear Queue


Let QUEUE[MAXSIZE] is an array for implementing the Linear Queue & NUM is the element
to be inserted in linear queue, FRONT represents the index number of the element at the
beginning of the queue and REAR represents the index number of the element at the end of the
Queue.

Step 1: Read NUM to be inserted in Linear Queue.


Step 12:If REAR = (MAXSIZE –1) : then
Write : “Queue Overflow” and return
[End of If ]
Step 3: If FRONT = –1 AND REAR=-1 : then
Set FRONT=0.
[End of If]
Step 4 : Set REAR := REAR + 1
Step 5 : Set QUEUE[REAR] := NUM
Step 6 : Exit

Function for insertion in a linear queue (using arrays)


void lqinsert()
{
int num;
if(rear==MAXSIZE-1)
{
printf("\nQueue is full (Queue overflow)");
return;
}
printf("\nEnter the element to be inserted : ");
scanf("%d",&num);
rear++;
queue[rear]=num;
if(front = = -1)
front=0;
}

2. Algorithm for Deletion from a Linear Queue


Let QUEUE[MAXSIZE] is an array for implementing the Linear Queue & NUM is the element
to be deleted from linear queue, FRONT represents the index number of the element at the
beginning of the queue and REAR represents the index number of the element at the end of the
Queue.

Step 1 : If FRONT = -1 : then


Write : “Queue Underflow” and return
[End of If]
Step 2 : Set NUM := QUEUE[FRONT]
Step 3 : Write “Deleted item is : ”, NUM
Step 4 : Set FRONT := FRONT + 1.
Step 5 : If FRONT>REAR : then
Set FRONT := REAR := -1.
[End of If]
Step 6 : Exit

Function for Deletion from a Linear Queue


void lqdelete()
{
if(front == -1)
{
printf("\nQueue is empty (Queue underflow)");
return;
}
int num;
num=queue[front];
printf("\nDeleted element is : %d",num);
front++;
if(front>rear)
front=rear=-1;
}
➢ Static implementation of Linear Queues using arrays(for integers)
#include <stdio.h>
#define MAX 3 // Changing this value will change length of array
int queue[MAX];
int front = -1, rear = -1;
void insertQ(void);
int deleteQ(void);
void display(void);
int main()
{
int option, val;
do
{
printf("\n\n ***** MAIN MENU *****");
printf("\n 1. Insert an element");
printf("\n 2. Delete an element");
printf("\n 3. Display the queue");
printf("\n 4. EXIT");
printf("\n Enter your option : ");
scanf("%d", &option);
switch(option)
{
case 1:insertQ();
break;
case 2: //val =
deleteQ();
//if (val != -1)
//printf("\n The number deleted is: %d", val);
break;
case 3:
display();
break;
}
}while(option != 4);
return 0;
}
void insertQ()
{
int num;
printf("\n Enter the number to be inserted in the queue : ");
scanf("%d", &num);
if(rear == MAX-1)
printf("\n OVERFLOW");
else if(front == -1 && rear == -1)
front = rear = 0;
else rear++;
queue[rear] = num;
}
int deleteQ()
{
int val;
if(front == -1 || front>rear)
{
printf("\n UNDERFLOW");
//return-1;
}
else
{
val = queue[front];
front++;
printf("value=%d",val);
if(front > rear)
front = rear = -1;
//return val;
}
}
void display ()
{
int i;
printf("\n");
if (front == -1 || front > rear)
printf("\n QUEUE IS EMPTY");
else
{
for(i = front;i <= rear;i++)
printf("\n %d", queue[i]);
}
}
➢ Static implementation of Linear Queues using arrays (for characters)
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define MAXQ 3
int front=0,rear=-1;
int Que[MAXQ];
int Isempty();
int Isfull();
char InsertQ(char);
char DeleteQ();
void Display();
int main()
{
char x;
int ch;
do
{
printf("\n 1-INSERT");
printf("\n 2-DELETE");
printf("\n 3-DISPLAY");
printf("\n 4-QUIT");
printf("\n Enter your choice:");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("\n Enter the element to be inserted:");
fflush(stdin);
x=getchar();
InsertQ(x);
break;
case 2:
x=DeleteQ();
printf("\n Delete element is %c\n:",putchar(x));
break;
case 3:
Display();
break;
case 4: exit(0);
break;
default:
printf("\n Wrong choice!Try again:");
}
}while(ch!=4);
return 0;
}
int Isempty()
{
if(rear<front)
return 1;
else
return 0;
}
int Isfull()
{
if(rear==MAXQ-1)
return 1;
else
return 0;
}

char InsertQ(char x)
{
if(Isfull())
{
printf("\n Queue full");
return x;
}
rear++;
Que[rear]=x;
}
char DeleteQ()
{
char x;
if(Isempty())
{
printf("\n Queue is empty");
exit(0);
}
x=Que[front];
front++;
return x;
}
void Display()
{
int i;
if(Isempty())
{
printf("\n Queue is empty");
return;
}
printf("\n Elements in the Queue are :\n");
for(i=front;i<=rear;i++)
{
fflush(stdin);
putchar(Que[i]);
}
}

2. Queue using Linked list:


We can represent a queue as a linked list. In a queue data is deleted from the front end and
inserted at the rear end. We can perform similar operations on the two ends of alist. We use two
pointers front and rear for our linked queue implementation.
The linked queue looks as shown in figure:

Queue operations work as follows:


1. Two pointers FRONT and REAR are used to keep track of the first and last elements in
the queue.
2. When initializing the queue, we set the value of FRONT and REAR to NULL.
3. Before enqueing, check if queue is full or not.
4. Create a Newnode(allocate memory) and Insert the value into Newnode.
5. If it is the first node, Set Newnode as REAR and FRONT
6. On enqueing an element, next of REAR will be changes as REAR.
7. Before dequeuing, check if queue is empty.
8. On dequeueing an element, assign a temporary pointer to point the FRONT
9. Next,we return the data of FRONT and change FRONT to point the next of FRONT
10. Free the Temporary pointer which is points to the delete node.

Algorithm for inserting an element in a Linear Queue:


Let PTR is the structure pointer which allocates memory for the new node & NUM is the
element to be inserted into linear queue, DATA represents the information part of the node and
LINK represents the link or next pointer pointing to the address of next node. FRONT
represents the address of first node, REAR represents the address of the last node. Initially,
before inserting first element in the queue, FRONT=REAR=NULL.

Step 1: Allocate memory for the new node using PTR.


Step 2: Read NUM to be inserted into linear queue.
Step 3: Set PTR->DATA = NUM
Step 4: Set PTR->LINK= NULL
Step 5: If FRONT = NULL: then
Set FRONT=REAR=PTR
Else
Set REAR->LINK=PTR;
Set REAR=PTR;
[End of If Else]
Step 6: Exit

Function for Inserting an element in a Linear Queue:


Void EnQueue()
{
struct queue *ptr;
int num;
ptr = (struct queue *) malloc (sizeof (struct queue));
printf("\nEnter element to be inserted in queue : ");
scanf("%d",&num);
ptr->data=num;
ptr->link=NULL;
if(front==NULL)
{
front=ptr;
rear=ptr;
}
else
{
rear->link=ptr;
rear=ptr;
}
}
Algorithm for Deleting a node from a Linear Queue:
Let PTR is the structure pointer which deallocates memory of the first node in the linear queue
& NUM is the element to be deleted from queue, INFO represents the information part of the
deleted node and LINK represents the link or next pointer of the deleted node pointing to the
address of next node. FRONT represents the address of first node, REAR represents the address
of the last node.
Step 1: If FRONT = NULL: then
Write ‘Queue is Empty (Queue Underflow)’ and return.
[End of If structure]
Step 2: Set PTR = FRONT
Step 3: Set NUM = PTR->DATA
Step 4: Write ‘Deleted element from linear queue is: NUM.
Step 5: Set FRONT = FRONT->LINK
Step 6: If FRONT = NULL: then
Set REAR = NULL.
[End of If].
Step 7: Deallocate memory of the node at the beginning of queue using PTR.
Step 8: Exit.

Function for deleting a node from a Linear Queue


void DeQueue()
{
if(front==NULL)
{
printf("\nQueue is empty (Queue underflow)");
return;
}
struct queue *ptr;
int num;
ptr=front;
num=ptr->data;
printf("\nThe deleted element is : %d",num);;
front=front->link;
if(front==NULL)
rear=NULL;
free(ptr);

➢ Dynamic implementation of linear queue using pointers


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

struct Node
{
int data;
struct Node *link;
}*front = NULL,*rear = NULL;
void enque(int);
void deque();
void display();

int main()
{
int choice, value;
printf("\n:: Queue Implementation using Linked List ::\n");
while(1)
{
printf("\n****** MENU ******\n");
printf("1. Insert\n2. Delete\n3. Display\n4. Exit\n");
printf("Enter your choice: ");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Enter the value to be insert: ");
scanf("%d", &value);
enque(value);
break;
case 2: deque();
break;
case 3: display();
break;
case 4: exit(0);
default: printf("\nWrong selection!!! Please try again!!!\n");
}
}
return 0;
}
void enque(int value)
{
struct Node *newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = value;
newNode -> link = NULL;
if(front == NULL)
front = rear = newNode;
else{
rear -> link = newNode;
rear = newNode;
}
printf("\nInsertion is Success!!!\n");
}
void deque()
{
if(front == NULL)
printf("\nQueue is Empty!!!\n");
else{
struct Node *temp = front;
front = front -> link;
printf("\nDeleted element: %d\n", temp->data);
free(temp);
}
}
void display()
{
if(front == NULL)
printf("\nQueue is Empty!!!\n");
else{
struct Node *temp = front;
while(temp->link != NULL){
printf("%d--->",temp->data);
temp = temp -> link;
}
printf("%d--->NULL\n",temp->data);
}
}

CIRCULAR QUEUES
• The queue that we implemented using an array suffers from one limitation. In that
implementation there is a possibility that the queue is reported as full (since rear has
reached the end of the array), even though in actuality there might be empty slots at the
beginning of the queue.
• To overcome this limitation, we can implement the queue as a circular queue. Here as we
go on adding elements to the queue and reach the end of the array, the next element is
stored in the first slot the array (provided it is free).
• Suppose an array arr of n elements is used to implement a circular queue we may reach
arr[n-1]. We cannot add any more elements to the queue since we have reached at the end
of the array. Instead of reporting the queue as full, if some elements in the queue have been
deleted then there might be empty slots at the beginning of the queue.
• In such a case these slots would be filled by new elements being added to the queue. In
short just because we have reached the end of the array, the queue would not be reported
as full. The queue would be reported as full only when all the slots in the array stand
occupied.
• For example, let us consider a linear queue status as follows:

Next insert another element, say 66 to the queue. We cannot insert 66 to the queue as the
rear crossed the maximum size of the queue (i.e., 5). There will be queue full signal. The
queue status is as follows:
This difficulty can be overcome if we treat queue position with index zero as a position
that comes after position with index four then we treat the queue as a circular queue. In
circular queue if we reach the end for inserting elements to it, it is possible to insert new
elements if the slots at the beginning of the circular queue are empty.
Representation of Circular Queue:
Let us consider a circular queue, which can hold maximum (MAX) of six elements.
Initially the queue is empty.

Now, insert 11 to the circular queue. Then circular queue status will be:

Insert new elements 22, 33, 44 and 55 into the circular queue. The circular queue status
is:

Now, delete an element. The element deleted is the element at the front of the circular
queue. So, 11 is deleted. The circular queue status is as follows:

Again, delete an element. The element to be deleted is always pointed to by the FRONT
pointer. So, 22 is deleted. The circular queue status is as follows:
Again, insert another element 66 to the circular queue. The status of the circular queue is:
22

Now, insert new elements 77 and 88 into the circular queue. The circular queue status is:

Now, if we insert an element to the circular queue, as COUNT = MAX we cannot add the
element to circular queue. So, the circular queue is full.

Operations on Circular queue:


Algorithm for Insertion in a Circular Queue
Let CQUEUE[MAXSIZE] is an array for implementing the Circular Queue, where
MAXSIZE represents the max. size of array. NUM is the element to be inserted in circular
queue, FRONT represents the index number of the element at the beginning of the queue
and REAR represents the index number of the element at the end of the Queue.

Step 1: If FRONT = (REAR + 1) % MAXSIZE: then


Write: “Queue Overflow” and return.
[End of If]
Step 2: Read NUM to be inserted in Circular Queue.
Step 3: If FRONT= -1: then
Set FRONT = REAR =0.
Else
Set REAR= (REAR + 1) % MAXSIZE.
[End of If Else]
Step 4: Set CQUEUE[REAR]=NUM;
Step 5: Exit
Function for Insertion in a Circular Queue using arrays:
void cqinsert()
{
int num;
if(front==(rear+1)%MAXSIZE)
{
printf("\nQueue is Full(Queue overflow)");
return;
}
printf("\nEnter the element to be inserted in circular queue : ");
scanf("%d",&num);
if(front==-1)
front=rear=0;
else
rear=(rear+1) % MAXSIZE;
cqueue[rear]=num;
}

Algorithm for Deletion from a Linear Queue:


Let CQUEUE[MAXSIZE] is an array for implementing the Circular Queue, where
MAXSIZE represents the max. size of array. NUM is the element to be deleted from
circular queue, FRONT represents the index number of the first element inserted in the
Circular Queue and REAR represents the index number of the last element inserted in the
Circular Queue.

Step 1: If FRONT = - 1: then


Write: “Queue Underflow” and return.
[End of If Structure]
Step 2: Set NUM = CQUEUE[FRONT].
Step 3: Write ‘Deleted element from circular queue is: ‘, NUM.
Step 4: If FRONT = REAR: then
Set FRONT = REAR = -1;
Else
Set FRONT = (FRONT + 1) % MAXSIZE.
Step 5: Exit

Function to Delete an element from a Queue


void cqdelete()
{
int num;
if(front==-1)
{
printf("\nQueue is Empty (Queue underflow)");
return;
}
num=cqueue[front];
printf("\nDeleted element from circular queue is : %d",num);
if(front==rear)
front=rear=-1;
else
front=(front+1) %MAXSIZE;
}

➢ implementation of Circular queue using arrays

#include<stdio.h>
#include<stdlib.h>
#define SIZE 3

int cq[SIZE];
int front = -1, rear = -1;

void insert_cq();
int delete_cq();
void display();

int main()
{
int ch;
printf("\nCircular Queue operations");
printf("\n Enter 1 to insert into queue");
printf("\n Enter 2 to delete element");
printf("\n Enter 3 to display element");
printf("\n Enter 4 to exit");
do
{
printf("\n Enter your choice: ");
scanf("%d",&ch);
switch(ch)
{
case 1: insert_cq();
break;
case 2: delete_cq();
break;
case 3: display();
break;
case 4:exit(0);
default:printf("Invalid input \n");
}
} while(1);
return 0;
}
int isFull() {
if ((front == rear + 1) || (front == 0 && rear == SIZE - 1)) return 1;
return 0;
}
int isEmpty() {
if (front == -1) return 1;
return 0;
}
void insert_cq()
{
int x;
if (isFull())
printf("\n Queue is full!! \n");
else
{
printf("\n Enter a value to insert: ");
scanf("%d",&x);
if (front == -1) front = 0;
rear = (rear + 1) % SIZE;
cq[rear] = x;
}
}
int delete_cq()
{
int x;
if (isEmpty())
{
printf("\n Queue is empty !! \n");
return (-1);
}
else
{
x= cq[front];
if (front == rear)
{
front = -1;
rear = -1;
}
else {
front = (front + 1) % SIZE;
}
printf("\n Deleted element -> %d \n", x);
return (x);
}

}
void display ()
{
int i;
if (isEmpty())
printf(" \n Empty Queue\n");
else {
printf("\n Front -> %d ", front);
printf("\n Items -> ");
for (i = front; i != rear; i = (i + 1) % SIZE) {
printf("%d ", cq[i]);
}
printf("%d ", cq[i]);
printf("\n Rear -> %d \n", rear);
}
}
Advantages of Circular queue over linear queue:
In a linear queue with max. size 5, after inserting element at the last location (4) of array, the
elements can’t be inserted, because in a queue the new elements are always inserted from the
rear end, and rear here indicates to last location of the array (location with subscript 4) even if
the starting locations before front are free. But in a circular queue, if there is element at the last
location of queue, then we can insert a new element at the beginning of the array.

You might also like