SE 2005
DATA
STRUCTURES
QUEUE
Real world examples Queues in computer science
Access to shared resources:
queue of print jobs to send to
the printer
People on an escalator or
waiting in line for payment
queue of network data queue of programs /
packets to send processes to be run
QUEUE
• A queue is a homogeneous collection of elements in which
– deletions can take place only at the front end, known as dequeue
– insertions can take place only at the rear end, known as enqueue.
• The working mechanism: The element to enter the queue first will be deleted from
the queue first (First-In-First-Out (FIFO) system).
STACK VS QUEUE
• One of the main difference between stacks and queues is in removing.
– In a stack we remove the item the most recently added;
– in a queue, we remove the item the least recently added.
• Also, significant structural difference is that the queue implementation needs to keep
track of the front and the rear of the queue, whereas the stack only needs to worry
about one end: the top.
OPERATIONS ON QUEUE
Empty condition (Front = Rear = -1)
Full condition (Rear = Max-1).
Two indexes (or pointers) called FRONT When enqueuing the first
and REAR are used to keep track of the element, we set the value of
first and last elements in the queue. FRONT and REAR to 0.
When initializing the queue, we set the
value of FRONT and REAR to -1.
HOW
On enqueuing an element, we
increase the value of REAR index
QUEUE
and place the new element in the
position pointed to by REAR.
WORKS Before enqueuing, we check if the
queue is already full.
On dequeuing an element, we return When dequeuing the last
the value pointed to by FRONT and element, we reset the values
increase the FRONT index. of FRONT and REAR to -1.
Before dequeuing, we check if the
queue is already empty.
EXERCISE
enqueue(8)
enqueue(3)
dequeue()
enqueue(2)
enqueue(5)
dequeue()
enqueue(9)
Front=-1 Queue is empty Front=1 Enqueue 2
1 5 3 2
0 1 2 3 4 0 1 2 3 4
Rear=-1 Rear=2
Front=0 enqueue 8 Front=1 Enqueue 5
2 8 6 3 2 5
0 1 2 3 4 0 1 2 3 4
Rear=0 Rear=3
Front=0 enqueue 3 Front=2 dequeue
3 8 3 7 2 5
0 1 2 3 4 0 1 2 3 4
Rear=1 Rear=3
Front=1 dequeue Front=2 Enqueue 9
4 3 8 2 5 9
0 1 2 3 4 0 1 2 3 4
Rear=1 Rear=4
THE TYPES OF QUEUE
• Types
– Simple Queue
• CPU scheduling, Disk Scheduling
• Synchronization between two process.
– Circular Queue
• Memory management, Traffic Management
– Deque
• To execute undo and redo operation.
– Priority Queue
• Sorting heap
• Representations
– Queue Representation with Array
– Queue Representation with Linked List
QUEUE REPRESENTATION WITH ARRAY
// A structure to represent a queue
struct Queue {
int front, rear;
unsigned capacity;
int* array;
};
Note: The queue may contain
MAX – 1 data.
struct Queue {
int front, rear;
unsigned capacity;
int* array;
};
struct Queue* createQueue(unsigned capacity) {
struct Queue* queue = (struct Queue*)malloc(sizeof(struct Queue));
queue->capacity = capacity;
queue->front = -1;
queue->rear = -1;
queue->array = (int*)malloc(queue->capacity * sizeof(int));
return queue;
}
// Queue is full when size becomes equal to the capacity
int isFull(struct Queue* queue) {
return (queue->rear == queue->capacity -1);
}
// Queue is empty when size is 0
int isEmpty(struct Queue* queue) {
return (q->front == -1 || q->front > q->rear);
}
void enqueue(struct Queue* queue, int item) {
if (isFull(queue))
return;
if(queue->front == -1)
queue->front++;
queue->array[++queue->rear] = item;
printf("%d enqueued to queue\n", item);
printf("\t%d %d\n", queue->rear, queue->front);
}
int dequeue(struct Queue* queue) {
if (isEmpty(queue))
return INT_MIN;
int item = queue->array[queue->front++];
return item;
}
It is known as a
boundary case problem.
Is this the only solution?
QUEUE REPRESENTATION WITH LINKED
LIST 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.
• The array implementation can
not be used for the large scale
applications where the queues
are implemented.
• One of the alternative of array
implementation is linked list
implementation of queue.
ALGORITHMS FOR ENQUEUE AND
DEQUEUE OPERATIONS
Queue Front : 40
Queue Rear : 50
COMPARISONS OF QUEUE REPRESENTATION
USING LINKED LIST OVER THE ARRAY
• The array is fixed size, therefore, a number of
elements will be limited in the queue. Since
linked list is dynamic and can be changed easily,
so the number of elements can be changed.
• The pointers in linked list consume additional
memory compared to an array.
• In array implementation, sometimes dequeue
operation not possible, although there are free
slots. This drawback can be overcome in linked
list representation
CIRCULAR QUEUE
• Boundary case problem in array implementation can be
overcome in two different ways.
– The first solution is by left-shifting all elements after
every deletion.
• However, this is not suitable since after every
deletion, the entire elements required shifting left
and front and rear should be readjusted according
to that.
– The second solution is by implementing a circular
queue.
• A circular queue (also known as a circular buffer) is
a linear data structure that uses a single, fixed-size
buffer as if it were connected end-to-end.
Example: Consider the following circular queue with N = 5.
1. Initially, Rear = 0, Front = 0. 4. Insert 20, Rear = 3, Front = 1.
Front
Rear
2. Insert 10, Rear = 1, Front = 1. 5. Insert 70, Rear = 4, Front = 1.
Rear Front
Front
Rear
3. Insert 50, Rear = 2, Front = 1. 6. Delete front, Rear = 4, Front = 2.
Front Rear Front
Rear
Note: Circular Queue‘s circularity is only logical. There cannot be a physical circularity in main memory.
7. Insert 100, Rear = 5, Front = 2. 10. Delete front, Rear = 1, Front = 3.
Front Rear
Front
Rear
8. Insert 40, Rear = 1, Front = 2. 11. Delete front, Rear = 1, Front = 4.
Rear
Rear Front
Front
9. Insert 140, Rear = 1, Front = 2. 12. Delete front, Rear = 1, Front = 5.
As Front = Rear + 1, so Queue overflow. Rear
Rear Front
Front
ALGORITHMS FOR ENQUEUE AND
DEQUEUE OPERATIONS
10 enqueued to queue
20 enqueued to queue
30 enqueued to queue
40 enqueued to queue
10 dequeued from queue
Front item is 20
Rear item is 40
#include <stdio.h>
#include <stdlib.h>
#define SIZE 6
struct Queue {
int front, rear, currSize;
unsigned maxSize;
int* a;
};
struct Queue* createQueue(unsigned maxSize) {
struct Queue* queue = (struct Queue*) malloc(sizeof(struct Queue));
queue->maxSize = maxSize;
queue->front = queue->rear = -1;
queue->a = (int*) malloc(queue->maxSize * sizeof(int));
return queue;
}
// Checking for Overflow condition
int isFull(struct Queue* queue){
if ((queue->front == queue->rear + 1) || (queue->front == 0 && queue->rear == queue->maxSize - 1)){
return 1;
}
return 0;
}
// Checking for Underflow condition
int isEmpty(struct Queue* queue){
if (queue->front == -1)
return 1;
return 0;
}
// Function to do dequeue
int dequeue(struct Queue* queue)
{
int item;
// Function to do enqueue if (isEmpty(queue))
void enqueue(struct Queue* queue,int value){ {
if (isFull(queue)) printf("Can't add the queue is empty \n");
printf("Can't add the queue is full \n"); return (-1);
}
else else
{ {
if (queue->front == -1) item = queue->a[queue->front];
queue->front = 0; if (queue->front == queue->rear)
{
queue->rear = (queue->rear + 1) % queue->maxSize; queue->front = queue->rear = -1 ;
queue->a[queue->rear] = value; }
printf("%d was added\n", value); else
} {
} queue->front = (queue->front + 1) % queue->maxSize;
}
printf("%d dequeued\n", item);
}
}
// Function to print the queue
void print(struct Queue* queue) {
int i;
if (isEmpty(queue))
printf("Empty Queue\n");
else {
printf("\nThe items in the queue are : \n");
for (i = queue->front; i != queue->rear; i = (i + 1) % queue->maxSize) {
printf("%d ", queue->a[i]);
}
printf("%d \n\n", queue->a[i]);
}
}
int main() {
struct Queue* queue = createQueue(6);
dequeue(queue);//Underflow condition
enqueue(queue,12);
enqueue(queue,14);
enqueue(queue,16);
enqueue(queue,18);
enqueue(queue,20);
print(queue);
dequeue(queue);
dequeue(queue);
print(queue);
enqueue(queue,22);
enqueue(queue,24);
enqueue(queue,26);
enqueue(queue,28);//Overflow condition
print(queue);
return 0;
}
A DOUBLE-ENDED QUEUE (DEQUE)
• A linear list that generalizes a queue, in which the insertion and deletion operations are
performed at both the ends (front and rear), but not in the middle (FIFO rule).
– It is also often called a head-tail linked list
• Deque can be represented in 2 ways;
– Input Restricted Double Ended Queue
– Output Restricted Double Ended Queue
A DOUBLE-ENDED QUEUE (DEQUE)
• Input Restricted Double Ended Queue: Insertions can be made at only one end of the
list but deletions can be made from both ends of the list
• Output Restricted Double Ended Queue: Deletions can be made from only one end
of the list but insertions can be made at both ends of the list
OPERATIONS
• There are four basic operations in usage of Deque.
– Insertion at rear end
– Insertion at front end
– Deletion at front end
– Deletion at rear end
• In addition to above operations, following operations are also
supported :
– getFront() : Gets the front item from queue.
– getRear() : Gets the last item from queue.
– isEmpty() : Checks whether Deque is empty or not.
– size() : Gets number of elements in Deque.
– erase() : Deletes all the elements from Deque.
INSERTION AT REAR END
FOR ARRAY IMPLEMENTATION
INSERTION AT FRONT END
FOR ARRAY IMPLEMENTATION
INSERTION
FOR LINKED LIST IMPLEMENTATION
Insertion at Front end : Insertion at Rear end :
DELETION AT FRONT END
FOR ARRAY IMPLEMENTATION
DELETION AT REAR END
FOR ARRAY IMPLEMENTATION
DELETION
FOR LINKED LIST IMPLEMENTATION
Deletion from Front end : Deletion from Rear end :
Examples
USING QUEUES: CODED MESSAGES
• A Caesar cipher is a substitution code that encodes
a message by shifting each letter in a message by a
constant amount k
• If k is 5, a becomes f, b becomes g, etc.
• Example: n qtaj ofaf
• Used by Julius Caesar to encode military messages
for his generals (around 50 BC)
• This code is fairly easy to break!
USING QUEUES: CODED MESSAGES
• Modern version: ROT13
• Each letter is shifted by 13
• “used in online forums as a means of hiding
spoilers, punchlines, puzzle solutions, and
offensive materials from the casual glance”
(Wikipedia)
USING QUEUES: CODED MESSAGES
• An improvement: change how much a letter is shifted
depending on where the letter is in the message
• A repeating key is a sequence of integers that determine
how much each character is shifted
• Example: consider the repeating key
3 1 7 4 2 5
• The first character in the message is shifted by 3, the next by 1, the
next by 7, and so on
• When the key is exhausted, start over at the beginning of the key
AN ENCODED MESSAGE USING A REPEATED
KEY
Encoded message
n o v a n g j h l m u u r x l v
Key 3 1 7 4 2 5 3 1 7 4 2 5 3 1 7 4
k n o w l e d g e i s p o w e r
Decoded message
6-46
USING QUEUES: CODED MESSAGES
• We can use a queue to store the values of the key
• dequeue a key value when needed
• After using it, enqueue it back onto the end of
the queue
• So, the queue represents the constantly cycling
values in the key
https://www.csd.uwo.ca/Courses/CS1027b/notes/queues.pdf