CSC 221 DSA Queue Arrays - Linked List Implementation 10032023 055715pm

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 59

CSC-221 DATA STRUCTURES AND ALGORITHMS

Instructor: Ayesha Jamal


Lecture : Queue & its Static & Dynamic implementation
QUEUE

2
QUEUE
A queue is an ordered collection of homogenous data items such that:
 Items can be removed only at one end (front of the queue)
 Items can be added only at the other end (rear of the queue)
 Accessing the elements of queues follows a First In, First Out (FIFO) order
Example: Customers standing in a check-out line in a store model a queue, the first customer in is
the first customer served.
4
QUEUE AS AN ADT

A Queue is a collection of items on which following operations are defined:


 Initialize the queue to be the empty queue.
 Determine whether or not the queue is empty.
 Determine whether or not the queue is full.
 If Queue is not full, insert a new item from the rear of the queue.
 If Queue is not empty, remove an item from the front of the queue.
 Retrieve the value at the front of the queue
ENQUEUE AND DEQUEUE

Primary queue operations: Enqueue and Dequeue

 Enqueue – insert an element at the rear of the queue.


 Dequeue – remove an element from the front of the queue.
APPLICATIONS OF QUEUES

Operating system
Multi-user/multitasking environments, where several users or task may be requesting the same resource
simultaneously

Printer Queue
Documents to be printed in a queue
LANDING AND TAKEOFF QUEUES
QUEUES VS. STACKS

 Stacks are a LIFO container: Store data in the reverse of order received
 Queues are a FIFO container: Store data in the order received
 Stacks then suggest applications where some sort of reversal or unwinding is desired.
 Queues suggest applications where service is to be rendered relative to order received.
 Stacks and Queues can be used in conjunction to compare different orderings of the
same data set.
 From an ordering perspective, then, Queues are the “opposite” of stacks.
QUEUES VS. STACK
QUEUE OPERATIONS

Mainly the following four basic operations are performed on queue:


 enqueue(): Adds an item to the queue. If the queue is full, then it is said
to be an Overflow condition. 
 dequeue(): Removes an item from the queue. If the queue is empty, then
it is said to be an Underflow condition. 
 is Full(): Check if queue is full.
 is Empty(): Check if queue is empty.
11
ENQUEUE OPERATION
 Queues maintain two data variables, front and rear. Therefore, its operations
are comparatively difficult to implement than that of stacks.
The following steps should be taken to enqueue (insert) data into a queue −
 Step 1 − Check if the queue is full.
 Step 2 − If the queue is full, produce overflow error and exit.
 Step 3 − If the queue is not full, increment rear to point the next empty space.
 Step 4 − Add data element to the queue location, where the rear is pointing.
 Step 5 − return success.
12
13
DEQUEUE OPERATION
 Accessing data from the queue is a process of two tasks − access the data
where front is pointing and remove the data after access.
The following steps are taken to perform dequeue operation −
 Step 1 − Check if the queue is empty.
 Step 2 − If the queue is empty, produce underflow error and exit.
 Step 3 − If the queue is not empty, access the data where front is pointing and
remove it.
 Step 4 − Increment front to point to the next available data element.
14

 Step 5 − Return success.


15
IMPLEMENTATION OF QUEUES

 Static

Queue is implemented by an array, and size of queue remains fix.

 Dynamic

A queue can be implemented as a linked list, and expand or shrink with each enqueue or dequeue
operation.
IMPLEMENTATION OF QUEUE

There are two ways to implement a queue: 


 Using array
 Using linked list

17
STATIC IMPLEMENTATION
An implementation of a queue requires:
 Storage for the data
 Markers for the front and rear of the queue

An array-based implementation would need structures like:


 myArray, an array to store the elements of the queue
 front, an index to track the front queue element
 rear, an index to track the rear queue element
Queue Implementation Using
Array
IMPLEMENTATION OF QUEUES
class Queue
{
private: /***** Data Members *****/
int myArray;
int size;
int front, rear;
public: /***** Function Members *****/
Queue(int);
bool isEmpty();
bool isFull();
void enqueue(int value);
int getFront();
int dequeue();
};
IMPLEMENTATION OF QUEUES

IMPLEMENTATION OF QUEUES

Queue::Queue(int s)
{
myArray = new int[s];
size = s;
front = rear = -1;
}
IMPLEMENTATION OF QUEUES

IsEmpty & IsFull OPERATION

bool Queue::isEmpty() bool Queue::isFull()


{ {
if (front == -1)&&(rear == -1) if (rear == size - 1)
return true; return true;
else else
return false; return false;
} }
IMPLEMENTATION OF QUEUES

ENQUEUE OPERATION
void Queue::enqueue(int value)
{
if (isFull()) //Queue is Full
cout<<“Queue is full”<<endl;
else if (isEmpty()) //Queue is Empty
{
front=rear=0;
}
else
{
rear++; //there is some element in queue
}
myArray[rear] = value;
}
DEQUEUE OPERATION

int Queue::dequeue() else


{ {
int data;
data=myArray[front];
if (isEmpty()) //Queue is Empty //there is some element in queue
{ front++;
cout<<“Queue is empty”<<endl;
}
}
else if(front==rear) return data;
{ }
data=myArray[front];
front=rear=-1;
}
IMPLEMENTATION OF QUEUES

int Queue::getFront()
{
if (isEmpty())
{
cout<<“Queue is empty”<<endl;
}
else
return myArray[front];
}
QUEUE USING ARRAY

 Pros: Easy to implement.


 Cons :  Fixed size, if the queue has a large number of enqueue and
dequeue operations, at some point (in case of linear increment of front
and rear indexes) we may not be able to insert elements in the queue even
if the queue is empty (this problem is avoided by using circular queue).

26
Queue Implementation Using
Linked List
LINKED QUEUES

Queues can be implemented using linked lists


 Enqueue operation is same as adding an element at the end of the list
 Dequeue operation is same as removing the first element from the list

28
ENQUEUE

29
DEQUEUE

30
LINKED QUEUE
class LinkedQueue
{
private:
Node * front;
Node * rear;
public:
LinkedQueue();
void Enqueue(int);
int Dequeue();
int Front();
void Display(); 31

};
LINKED QUEUE
LinkedQueue::LinkedQueue(){
front = NULL;
rear = NULL;
}
void LinkedQueue::Display() {
Node* temp = front;
while(temp != NULL)
{
cout<<temp->data<<endl;
temp = temp->next;
}
32

}
ENQUEUE – ILLUSTRATION

front rear
Node* temp = new Node;
temp->data =x;
temp->next = NULL;
rear->next = temp;
rear = temp; rear temp
ENQUEUE OPERATION
void LinkedQueue:: Enqueue(int x) {
Node* temp = new Node;
temp->data =x;
temp->next = NULL;
if(front == NULL && rear == NULL) //List is empty
{
front = rear = temp;
}
else
rear->next = temp; //List is not empty 34

rear = temp;}
DEQUEUE – ILLUSTRATION

front temp front rear

temp = front;
front = front->next;
delete temp;

front rear 35
DEQUEUE – ILLUSTRATION (LIST HAS ONE NODE ONLY)

temp

front rear front rear


temp = front;
front = rear = NULL;
delete temp;

36
DEQUEUE OPERATION
void LinkedQueue:: Dequeue()
{
Node* temp = front;
if(front == NULL)
{ cout<<"Queue is Empty\n"; return; }
else if(front == rear)
{ front = rear = NULL; }
else
{front = front->next; }
delete temp; 37

}
LINKED QUEUE FRONT OPERATION

int LinkedQueue::Front()
{
if(front == NULL)
{
cout<<"Queue is empty\n“;
return -1;
}
else
return front->data;
}
38
REAL LIFE APPLICATIONS OF QUEUE
1) When a resource is shared among multiple consumers. Examples include CPU
scheduling, Disk Scheduling. 
2) When data is transferred asynchronously (data not necessarily received at same rate as
sent) between two processes. Examples include IO Buffers, pipes, file IO, etc. 
3) In Operating systems:
       a) Semaphores
       b) FCFS ( first come first serve) scheduling, example: FIFO queue
       c) Spooling in printers
       d) Buffer for devices like keyboard
4) In Networks:
       a) Queues in routers/ switches 
       b) Mail Queues 39
Circular Queue
CIRCULAR QUEUE
 Solution: Shifting of elements?
 Shifting – Inefficient esp. when elements are large records
 Would prefer to let the data “wrap-around” to the beginning
 Use a circular array to implement the queue
 In this implementation, first position follows the last

0 1 2 3 4 5 6 7

myArray 44 55 11 22 33
CIRCULAR QUEUE
0 1 2 3 4
front= 3
myArray 15 rear = 4

front rear
Allow rear to wrap around the array.
if(rear == size-1)
rear = 0;
else
rear++;
Equivalently:
rear = (rear + 1) % size;
IMPORTANT

 Initialize both front and rear to 0.


front
rear 0 7 Queue::Queue()
{
front = rear= 0;
1 6 }

2 5

3 4
CIRCULAR QUEUE

enqueue(70); front
front
rear 0 7
0 7

70
rear
1 6 1 6

2 5 2 5

3 4 3 4
CIRCULAR QUEUE
front
0 7

70
enqueue(70);
enqueue(80);
1 80 6

rear 5
2

3 4
CIRCULAR QUEUE
front

0 7

enqueue(70); 70
enqueue(80);
enqueue(90); 1 80 6

90
2 5

3 4

rear
CIRCULAR QUEUE
void Queue::enqueue(int value)
{
if (! isFull())
{
myArray[rear] = value;
rear = (rear + 1) % size;
}
else
cout<<“Queue Overflow”;
}
CIRCULAR QUEUE

front 0 7
0 7 front
70
70
1 80 6
1 80 6

dequeue();

90
5
90 2
2 5

3 4
3 4

rear rear
CIRCULAR QUEUE
0 7

dequeue();
dequeue(); 1 6

int Queue::dequeue()
{ front 90
5
if (! isEmpty()) { 2

int val= myArray[front] ;


front = (front + 1) % size; 3 4

return val;}
else
cout<<“Queue Underflow”; rear
return -1;
CIRCULAR QUEUE
rear
0 7

90

enqueue(50); 1 80 6

enqueue(60);
enqueue(70);
enqueue(80); 70
front 90
enqueue(90); 2 5

50 60
3 4
EMPTY VS. FULL QUEUE
rear
front
enqueue(30); 0
rear 0 7 enqueue(40);
7

90

1 80 6
1 6

90 70
front 5
2
2 5

50 60
3 4
3 4
EMPTY VS. FULL QUEUE

front
0
rear 0 7
7

30 90

1 80 6
1 6 40

rear
90 70
2 5
2 5 front
50 60
3 4
3 4

front == rear; //Empty or full?


HOW TO DISTINGUISH B/W EMPTY AND FULL QUEUES

 Can be tricky
 Use a counter variable to keep track of number of elements in the queue

class Queue
{
private:
int *myArray;
int front, rear, size;
int count;
};
class Queue
{
/***** Function Members *****/
public:
Queue(int);
bool isEmpty();
bool isFull();
void enqueue(int value);
int getFront();
int dequeue();
/***** Data Members *****/
private:
int *myArray;
int front, rear, count, size;
};
ISFULL & ISEMPTY
Queue::Queue(int s)
{
myArray=new int[s];
size = s;
front = rear = count =0;
}
bool Queue::isEmpty() bool Queue::isFull()
{ {
if (count == 0) if (count == size)
return true;
return true;
else
return false;
else
} return false;
}
DISPLAY FRONT

int Queue::getFront()
{
if (!isEmpty())
{
return myArray[front];
}
else
return -1;
}
ENQUEUE OPERATION

void Queue::enqueue(int value)


{
if (! isFull()){
myArray[rear] = value;
rear = (rear + 1) % size;
count++;
}
}
DEQUEUE OPERATION

int Queue::dequeue()
{
if (! isEmpty()) {
int val= myArray[front]
;
front = (front + 1) %
size;
count--;
return val;}
else
cout<<“Queue Underflow”;
58
return -1;
}
TRAVERSE QUEUE
void Queue::display()
{
int f=front, r=rear;
if (! isEmpty()) {
while(f!=r)
{
cout<<myArray[f];
front = (front + 1) % size;
}
else
59
cout<<“Queue is empty”;
}

You might also like