0% found this document useful (0 votes)
70 views19 pages

Unit - 5 Priority Queue

The document discusses priority queues, which are an extension of regular queues that orders elements based on priority. Elements with higher priority will be dequeued before lower priority elements. It provides an example comparing processing requests in a regular FIFO queue versus a priority queue ordered by processing time. Using a priority queue reduces the average wait time. Key properties and implementations using arrays, linked lists, and binary heaps are described.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
70 views19 pages

Unit - 5 Priority Queue

The document discusses priority queues, which are an extension of regular queues that orders elements based on priority. Elements with higher priority will be dequeued before lower priority elements. It provides an example comparing processing requests in a regular FIFO queue versus a priority queue ordered by processing time. Using a priority queue reduces the average wait time. Key properties and implementations using arrays, linked lists, and binary heaps are described.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Priority queue

Priority Queue is an extension of queue with following properties.

1. Every item has a priority associated with it.


2. An element with high priority is dequeued before an element with low priority.
3. If two elements have the same priority, they are served according to their order in the queue.

In the normal queue data structure, insertion is performed at the end of the queue and deletion is performed based on

the FIFO principle. This queue implementation may not be suitable for all applications.

Consider a networking application where the server has to respond for requests from multiple clients using queue data

structure. Assume four requests arrived at the queue in the order of R1, R2, R3 & R4 where R1 requires 20 units of

time, R2 requires 2 units of time, R3 requires 10 units of time and R4 requires 5 units of time. A queue is as follows...

Now, check to wait time of each request that to be completed.

1. R1 : 20 units of time

2. R2 : 22 units of time (R2 must wait until R1 completes 20 units and R2 itself requires 2 units. Total 22

units)

3. R3 : 32 units of time (R3 must wait until R2 completes 22 units and R3 itself requires 10 units. Total 32

units)

4. R4 : 37 units of time (R4 must wait until R3 completes 35 units and R4 itself requires 5 units. Total 37

units)

Here, the average waiting time for all requests (R1, R2, R3 and R4) is (20+22+32+37)/4 ≈ 27 units of time.

That means, if we use a normal queue data structure to serve these requests the average waiting time for each request

is 27 units of time.

Now, consider another way of serving these requests. If we serve according to their required amount of time, first we

serve R2 which has minimum time (2 units) requirement. Then serve R4 which has second minimum time (5 units)
requirement and then serve R3 which has third minimum time (10 units) requirement and finally R1 is served which has

maximum time (20 units) requirement.

Now, check to wait time of each request that to be completed.

1. R2 : 2 units of time

2. R4 : 7 units of time (R4 must wait until R2 completes 2 units and R4 itself requires 5 units. Total 7

units)

3. R3 : 17 units of time (R3 must wait until R4 completes 7 units and R3 itself requires 10 units. Total 17

units)

4. R1 : 37 units of time (R1 must wait until R3 completes 17 units and R1 itself requires 20 units. Total 37

units)

Here, the average waiting time for all requests (R1, R2, R3 and R4) is (2+7+17+37)/4 ≈ 15 units of time.

From the above two situations, it is very clear that the second method server can complete all four requests with very

less time compared to the first method. This is what exactly done by the priority queue.

Priority queue is a variant of a queue data structure in which insertion is performed in the order of arrival and

deletion is performed based on the priority.

There are two types of priority queues they are as follows...

1. Max Priority Queue


2. Min Priority Queue

1. Max Priority Queue


In a max priority queue, elements are inserted in the order in which they arrive the queue and the maximum value is
always removed first from the queue. For example, assume that we insert in the order 8, 3, 2 & 5 and they are removed
in the order 8, 5, 3, 2.

The following are the operations performed in a Max priority queue...

1. isEmpty() - Check whether queue is Empty.


2. insert() - Inserts a new value into the queue.
3. findMax() - Find maximum value in the queue.
4. remove() - Delete maximum value from the queue.

Min Priority Queue


Min Priority Queue is similar to max priority queue except for the removal of maximum element first. We remove
minimum element first in the min-priority queue.
The following operations are performed in Min Priority Queue...

1. isEmpty() - Check whether queue is Empty.


2. insert() - Inserts a new value into the queue.
3. findMin() - Find minimum value in the queue.
4. remove() - Delete minimum value from the queue.

Implementation of Priority Queue


Priority queue can be implemented using

 an array,
 a linked list,
 a heap data structure or a binary search tree.

Among these data structures, heap data structure provides an efficient implementation of
priority queues.

Using an Array 8,3,2,5


In this representation, elements are inserted according to their value in decreasing order and largest element is deleted
first from max priority queue.

For example, assume that elements are inserted in the order of 8, 5, 3 and 2. And they are removed in the order 8, 5, 3
and 2.

Now, let us analyze each operation according to this representation...


isEmpty() - If 'front == -1' queue is Empty. This operation requires O(1) time complexity which means constant time
complexity.

insert() - New element is added at a particular position based on the decreasing order of elements which
requires O(n) time complexity as it needs to shift existing elements inorder to insert new element in decreasing order.
This insert() operation requires O(n) time complexity.

findMax() - Finding the maximum element in the queue is very simple because maximum element is at the
beginning of the queue. This findMax() operation requires O(1) time complexity.

remove() - To remove an element from the max priority queue, first we need to find the largest element
using findMax() operation which requires O(1) time complexity, then that element is deleted with constant time
complexity O(1) and finally we need to rearrange the remaining elements in the list which requires O(n) time
complexity. This remove() operation requires O(1) + O(1) + O(n) ≈ O(n) time complexity.

Using Linked List


In this representation, we use a single linked list to represent max priority queue. In this representation, elements are
inserted according to their value in increasing order and a node with the maximum value is deleted first from the max
priority queue.

For example, assume that elements are inserted in the order of 2, 3, 5 and 8. And they are removed in the order of 8, 5,
3 and 2.

Using heap data structure


Heap data structure is a specialized binary tree-based data structure. Heap is a binary tree with special characteristics.
In a heap data structure, nodes are arranged based on their values. A heap data structure some times also called as
Binary Heap.

There are two types of heap data structures and they are as follows...

1. Max Heap
2. Min Heap

Every heap data structure has the following properties...


Property #1 (Ordering): Nodes must be arranged in an order according to their values based on Max heap or Min
heap.
Property #2 (Structural): All levels in a heap must be full except the last level and all nodes must be filled from left to
right strictly.

Max Heap
Max heap data structure is a specialized full binary tree data structure. In a max heap nodes are arranged based on
node value.

Max heap is defined as follows...

Max heap is a specialized full binary tree in which every parent node contains greater or equal value than its
child nodes.

Operations on Max Heap


The following operations are performed on a Max heap data structure...

1. Finding Maximum
2. Insertion
3. Deletion

Finding Maximum Value Operation in Max Heap


Finding the node which has maximum value in a max heap is very simple. In a max heap, the root node has the
maximum value than all other nodes. So, directly we can display root node value as the maximum value in max heap.

Insertion Operation in Max Heap


Insertion Operation in max heap is performed as follows...

 Step 1 - Insert the newNode as last leaf from left to right.


 Step 2 - Compare newNode value with its Parent node.
 Step 3 - If newNode value is greater than its parent, then swap both of them.
 Step 4 - Repeat step 2 and step 3 until newNode value is less than its parent node (or) newNode reaches to
root.

Example
Consider the above max heap. Insert a new node with value 85.

 Step 1 - Insert the newNode with value 85 as last leaf from left to right. That means newNode is added as a
right child of node with value 75. After adding max heap is as follows...

Step 2 - Compare newNode value (85) with its Parent node value (75). That means 85 > 75
Step 3 - Here newNode value (85) is greater than its parent value (75), then swap both of them. After swapping, max
heap is as follows.

Step 4 - Now, again compare newNode value (85) with its parent node value (89).

Here, newNode value (85) is smaller than its parent node value (89). So, we stop insertion process. Finally, max heap
after insertion of a new node with value 85 is as follows...
Deletion Operation in Max Heap
In a max heap, deleting the last node is very simple as it does not disturb max heap properties.

Deleting root node from a max heap is little difficult as it disturbs the max heap properties. We use the following steps to
delete the root node from a max heap...

Step 1 - Swap the root node with last node in max heap

Step 2 - Delete last node.

Step 3 - Now, compare root value with its left child value.

Step 4 - If root value is smaller than its left child, then compare left child with its right sibling. Else goto Step 6

Step 5 - If left child value is larger than its right sibling, then swap root with left child otherwise swap root with
its right child.

Step 6 - If root value is larger than its left child, then compare root value with its right child value.

Step 7 - If root value is smaller than its right child, then swap root with right child otherwise stop the process.

Step 8 - Repeat the same until root node fixes at its exact position.

Example
Consider the above max heap. Delete root node (90) from the max heap.

Step 1 - Swap the root node (90) with last node 75 in max heap. After swapping max heap is as follows...

Step 2 - Delete last node. Here the last node is 90. After deleting node with value 90 from heap, max heap is as
follows...
Step 3 - Compare root node (75) with its left child (89).

Here, root value (75) is smaller than its left child value (89). So, compare left child (89) with its right sibling (70).

Step 4 - Here, left child value (89) is larger than its right sibling (70), So, swap root (75) with left child (89).
Step 5 - Now, again compare 75 with its left child (36).

Here, node with value 75 is larger than its left child. So, we compare node 75 with its right child 85.

Step 6 - Here, node with value 75 is smaller than its right child (85). So, we swap both of them. After swapping max
heap is as follows.
Step 7 - Now, compare node with value 75 with its left child (15).

Here, node with value 75 is larger than its left child (15) and it does not have right child. So we stop the process.

Finally, max heap after deleting root node (90) is as follows...


1) Construct max heap for the following list of elements

35 33 42 10 14 19 27 44 26 31

2) Construct min heap for the following list of elements

35 33 42 10 14 19 27 44 26 31

Applications of Priority Queue:


1) CPU Scheduling
2) Graph algorithms like Dijkstra’s shortest path algorithm, Prim’s Minimum Spanning Tree, etc
3) All queue applications where priority is involved.

Quick sort
QuickSort is a Divide and Conquer algorithm. It picks an element as pivot and partitions the given array
around the picked pivot. There are many different versions of quickSort that pick pivot in different ways.
1. Always pick first element as pivot.
2. Always pick last element as pivot (implemented below)
3. Pick a random element as pivot.
4. Pick median as pivot.
Although there are many different ways to choose the pivot value, we will simply use the first item in the list. The role of
the pivot value is to assist with splitting the list. The actual position where the pivot value belongs in the final sorted list,
commonly called the split point, will be used to divide the list for subsequent calls to the quick sort.

Quicksort partitions an array and then calls itself recursively twice to sort the two resulting subarrays. This
algorithm is quite efficient for large-sized data sets

Algorithm
Quicksort is a divide and conquer algorithm.
It divides the large array into smaller sub-arrays. And then quicksort recursively sort the sub-arrays.
Pivot
1. Picks an element called the "pivot".
Partition
2. Rearrange the array elements in such a way that the all values lesser than the pivot should come before
the pivot and all the values greater than the pivot should come after it.
This method is called partitioning the array. At the end of the partition function, the pivot element will be
placed at its sorted position.
Recursive
3. Do the above process recursively to all the sub-arrays and sort the elements.
Base Case
If the array has zero or one element, there is no need to call the partition method.
So we need to stop the recursive call when the array size is less than or equal to 1.
Quick sort program

#include<stdio.h>

void quicksort(int [10],int,int);

int main(){

int x[20],size,i;

printf("Enter size of the array: ");

scanf("%d",&size);

printf("Enter %d elements: ",size);

for(i=0;i<size;i++)

scanf("%d",&x[i]);

quicksort(x,0,size-1);

printf("Sorted elements: ");

for(i=0;i<size;i++)

printf(" %d",x[i]);

return 0;

void quicksort(int x[10],int first,int last){

int pivot,j,temp,i;
if(first<last){

pivot=first;

i=first+1;

j=last;

while(i<j){

while(x[i]<=x[pivot]&&i<last)

i++;

while(x[j]>x[pivot])

j--;

if(i<j){

temp=x[i];

x[i]=x[j];

x[j]=temp;

temp=x[pivot];

x[pivot]=x[j];

x[j]=temp;

quicksort(x,first,j-1);

quicksort(x,j+1,last);

}
Merge Sort
Like QuickSort, Merge Sort is a Divide and Conquer algorithm. It divides input array in two halves, calls
itself for the two halves and then merges the two sorted halves. The merge() function is used for merging
two halves. The merge(arr, l, m, r) is key process that assumes that arr[l..m] and arr[m+1..r] are sorted and
merges the two sorted sub-arrays into one. See following C implementation for details.
MergeSort(arr[], l, r)
If r > l
1. Find the middle point to divide the array into two halves:
middle m = (l+r)/2
2. Call mergeSort for first half:
Call mergeSort(arr, l, m)
3. Call mergeSort for second half:
Call mergeSort(arr, m+1, r)
4. Merge the two halves sorted in step 2 and 3:
Call merge(arr, l, m, r)
The following diagram from wikipedia shows the complete merge sort process for an example array {38,
27, 43, 3, 9, 82, 10}.
Merge sort program
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;

/* create temp arrays */


int L[n1], R[n2];

/* Copy data to temp arrays L[] and R[] */


for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];

/* Merge the temp arrays back into arr[l..r]*/


i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}

/* Copy the remaining elements of L[], if there


are any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}

/* Copy the remaining elements of R[], if there


are any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}

/* l is for left index and r is right index of the


sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l+(r-l)/2;

// Sort first and second halves


mergeSort(arr, l, m);
mergeSort(arr, m+1, r);

merge(arr, l, m, r);
}
}

/* Driver program to test above functions */


int main()
{
int arr[] = {12, 11, 13, 5, 6, 7};
int size = sizeof(arr)/sizeof(arr[0]);

printf("Given array is \n");


for (i=0; i < size; i++)
printf("%d ", arr[i]);

mergeSort(arr, 0, size - 1);

printf("\nSorted array is \n");


for (i=0; i < size; i++)
printf("%d ", arr[i]);

return 0;
}

Radix sort
The lower bound for Comparison based sorting algorithm (Merge Sort, Heap Sort, Quick-Sort .. etc) is
Ω(nLogn), i.e., they cannot do better than nLogn.
Counting sort is a linear time sorting algorithm that sort in O(n+k) time when elements are in range from 1
to k.

Radix sort is a sorting technique that sorts the elements by first grouping the individual digits of the
same place value. Then, sort the elements according to their increasing/decreasing order.
Algorithm:
For each digit i where i varies from the least significant digit to the most significant digit of a number
Sort input array using countsort algorithm according to ith digit.

We used count sort because it is a stable sort.

Example: Assume the input array is:


10,21,17,34,44,11,654,123
Based on the algorithm, we will sort the input array according to the one's digit (least significant digit).
0: 10
1: 21 11
2:
3: 123
4: 34 44 654
5:
6:
7: 17
8:
9:

So, the array becomes 10,21,11,123,24,44,654,17


Now, we'll sort according to the ten's digit:
0:
1: 10 11 17
2: 21 123
3: 24
4: 44
5: 654
6:
7:
8:
9:

Now, the array becomes : 10,11,17,21,123,34,44,654

Finally , we sort according to the hundred's digit (most significant digit):


0: 010 011 017 021 034 044
1: 123
2:
3:
4:
5:
6: 654
7:
8:
9:

The array becomes : 10,11,17,21,34,44,123,654 which is sorted. This is how our algorithm works.

Radix sort Program


#include<stdio.h>

int getMax(int arr[], int n) {


int max = arr[0];
int i;
for (i = 1; i < n; i++)
if (arr[i] > max)
max = arr[i];
return max;
}

void countSort(int arr[], int n, int exp) {


int output[n]; // output array
int i, count[10] = { 0 };

// Store count of occurrences in count[]


for (i = 0; i < n; i++)
count[(arr[i] / exp) % 10]++;

for (i = 1; i < 10; i++)


count[i] += count[i - 1];

// Build the output array


for (i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}

for (i = 0; i < n; i++)


arr[i] = output[i];
}

// The main function to that sorts arr[] of size n using Radix Sort
void radixsort(int arr[], int n) {
int m = getMax(arr, n);

int exp;
for (exp = 1; m / exp > 0; exp *= 10)
countSort(arr, n, exp);
}

void print(int arr[], int n) {


int i;
for (i = 0; i < n; i++)
printf("%d ", arr[i]);
}

int main() {
int arr[] = { 170, 45, 75, 90, 802, 24, 2, 66 };
int n = sizeof(arr) / sizeof(arr[0]);
radixsort(arr, n);
print(arr, n);
return 0;
}

Heap sort Program


#include <stdio.h>

// To heapify a subtree rooted with node i which is


// an index in arr[]. n is size of heap
void heapify(int arr[], int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2*i + 1; // left = 2*i + 1
int r = 2*i + 2; // right = 2*i + 2

// If left child is larger than root


if (l < n && arr[l] > arr[largest])
largest = l;

// If right child is larger than largest so far


if (r < n && arr[r] > arr[largest])
largest = r;

// If largest is not root


if (largest != i)
{
swap(arr[i], arr[largest]);

// Recursively heapify the affected sub-tree


heapify(arr, n, largest);
}
}

// main function to do heap sort


void heapSort(int arr[], int n)
{
// Build heap (rearrange array)
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);

// One by one extract an element from heap


for (int i=n-1; i>0; i--)
{
// Move current root to end
swap(arr[0], arr[i]);

// call max heapify on the reduced heap


heapify(arr, i, 0);
}
}

// main function
int main()
{
int arr[] = {12, 11, 13, 5, 6, 7};
int n = sizeof(arr)/sizeof(arr[0]);

heapSort(arr, n);

printf("Sorted array is \n");

for (int i=0; i<n; ++i)


printf(“%d”, arr[i]);
}

You might also like