Queues in Data Structures Using C
Queues in Data Structures Using C
Queue is a special type of data structure ( an ordered collection of items ) where elements are inserted from one
end and elements are deleted from other end. The end at which new elements are added is called rear and the end from
which elements are deleted is called the front. So , Queue is called First In First Out ( FIFO ) data structure.
front rear
from above fig., we observe that ,
1. The queue is represented sequentially using one-dimensional array with two variables front and rear.
2. The variable front is used as index to access the first element.
3. The variable rear is used as index to access the last element.
4. Elements are inserted into the queue in the order A0 , A1 , A2 , ………….. An-1 . i.e. we insert A0 first , A1 next
and so on. Item An-1 is inserted at the end.
5. Element A0 is the first element and it is at the front of queue.
6. Element An-1 is the last element inserted and it is at the rear end of queue.
7. Items are deleted from the front end in the order A0 , A1 , A2 , ………….. An-1.
1. Create Queue :
A. The createq ( QUE_SIZE ) function can be implemented as a single dimensional array q[ QUE_SIZE]
where QUE_SIZE is a symbolic constant and specifies the maximum number of elements that can be
inserted into the queue. This can be defined as shown below ,
#define QUE_SIZE 5
B. q is an array which is used to hold the elements of the queue as shown below ;
a. q[ 0 ] holds the 0th element.
b. q[ 1 ] holds the1st element.
c. q[ 2 ] holds the 2nd element , so on can be defined as int q[ QUE_SIZE ] ;
C. The variable front and rear are associated with array q and holds the index of the first element and
index of the rear element. If itemis the element that is inserted into the queue for the first time, then
we write as q[ 0 ] = item
30 20 30 20 25
-1 0 1 2 3 -1 0 1 2 3
30 20 25 10 30 20 25 10
-1 0 1 2 3 -1 0 1 2 3
30 20 25 10 20 25 10
-1 0 1 2 3 -1 0 1 2 3
25 10 10
-1 0 1 2 3 -1 0 1 2 3
-1 0 1 2 3 -1 0 1 2 3
front rear
the content of the queue are displayed from the front to rear. So,
first item to be displayed is 20
next item to be displayed is 25
final item to be displayed is 10
void main ( ) {
int ch , item , front , rear , q [ 10 ] ;
/**** Intially Queue is Empty ****/
front = 0 ; // front end of queue
rear = 0 ; // rear end of queue
for ( ; ; ) {
printf ( “ \n 1. Insert \t 2. Delete \t 3. Display 4. Exit \n Enter Your Choice :\t “ ) ;
scanf ( “%d” , &ch ) ;
switch ( ch ) {
case 1 : printf ( “Enter the item to be inserted :\t” ) ;
scanf ( “%d”, &item ) ;
inset_q ( item , &rear , q ) ;
break ;
case 2 : item = delete_q ( &front , &rear , q );
if ( item == -1 )
printf ( “ Queue is empty “ ) ;
else
printf ( “Deleted item :\t%d” , item ) ;
break ;
case 3 : diplay_q ( front , rear , q ) ;
break ;
case 4 : exit ( 0 ) ;
} // switch
} //for loop
} // main
0 1 2 3 4
30 40 50
The above situation arises when 5 elements say 10 20 30 40 50 are inserted and then deleting first 2 items 10 and
20. Now , if we try to insert an item we get the message , queue Overflow.
But in the above situation, rear insertion is denied even if space is available at the front end. This is because e in
our function , before inserting an element , we test whether rear is equal to QUE_SIZE -1. If so, we say queue is full and
cannot insert. This disadvantage can be overcome using 2 methods.
Method 1 : shift left -
After deleting the element from the front , shift all remaining elements to the left , as shown ;
front rear front rear
0 1 2 3 4 0 1 2 3 4
10 20 30 40 50 20 30 40 50
After inserting 10 20 30 40 50 After deleting 10 , shift remaining elements to left
0 1 2 3 4 0 1 2 3 4
30 40 50 40 50
After deleting 20 , shift remaining After deleting 30 , shift remaining
elements to left elements to left
Each time when an item is deleted , all the elements towards the right are moved to left by one position
and rear is decremented by 1. But, shifting the data is costly in terms of computer time if the data being stored is
very large. So , this method is not recommended.
Circular Queue :-
If the elements of a given queue can be stored efficiently in an array so as to “wrap around” so that end of the
queue is followed by the front of queue then it is called circular queue.
The pictorial representation and its equivalent representation using an array are given side by side in figure below,
rear
2
3 q 10 20 30 40 50
30
0 1 2 3 4
20
1 front rear
4 10
0 front
This circular representation allows the entire array to store the elements without shifting any data
within the queue. This is efficient way of implementing queues.
Create :
The create function can be implemented as a single dimensional array q [ QUE_SIZE ] where,
1. QUE_SIZE is a symbolic constant and specifies the maximum number of elements can be inserted into
the queue, defined as,
#define QUE_SIZE 5
2. q is an array which is used to hold the elements of the queue and defined as,
int q [ QUE_SIZE ] ;
when queue is empty, the values of index variables front and rear are initialized as,
int front = 0 , rear = -1 ;
using values of front and rear , it is very difficult to say when queue is full and when queue is
empty. For this purpose, we also use another variable count which keeps track number of elements in the
queue. When no elements are there in queue, the number of elements will be 0 and hence count is
initialized to 0 as,
int count = 0 ; // Queue is empty
so, create_q can be implemented as ,
#defined QUE_SIZE 5
int q[ QUE_SIZE ] ; // as global variables
int front = 0 , rear = -1 , count = 0 ; // as global variables
Insert Circular Queue :
Various steps to be followed while inseting the elements into queues ,
1. Check for Overflow :before inserting, we check whether sufficient space is available in the queue. This can
be done using the code as,
if ( count == QUE_SIZE ){
printf ( “ Queue is full\n” ) ;
return ;
}
2. Insert item :Increment rear by 1 and then take the mod operation and then insert the item as,
rear = ( rear + 1 ) % QUE_SIZE ;
q [ rear ] = item ;
3. Update count : as we insert an element into queue, we update count by 1 as,
count++ ;
the complete code can be written as,
void insert_cq ( ) {
if ( count == QUE_SIZE ) {
printf ( “\nQueue Overflow!!!” ) ;
return ;
}
void main ( ) {
int ch , item , front , rear , count , q [ QUE_SIZE ] ;
/**** Intially Queue is Empty ****/
front = 0 ; // front end of queue
rear = -1 ; // rear end of queue
count = 0 ; // empty queue
for ( ; ; ) {
printf ( “ \n 1. Insert \t 2. Delete \t 3. Display 4. Exit \n Enter Your Choice :\t “ ) ;
scanf ( “%d” , &ch ) ;
switch ( ch ) {
case 1 : printf ( “Enter the item to be inserted :\t” ) ;
scanf ( “%d”, &item ) ;
inset_q ( item , &rear , q , &count ) ;
break ;
case 2 : item = delete_cq ( &front , &count , q );
if ( item == -1 )
printf ( “ Queue is empty “ ) ;
else
printf ( “Deleted item :\t%d” , item ) ;
break ;
case 3 : diplay_cq ( front , count , q ) ;
break ;
case 4 : exit ( 0 ) ;
} // switch
} //for loop
} // main
/*************** inset_cq ( ) **************/
void inset_cq (int item , int *rear , int *q , int *count ) {
/******** check for overflow *********/
if ( *count == QUE_SIZE ) {
printf ( “\nQueue Overflow!!!” ) ;
return ;
}
*rear = ( *rear + 1 ) % QUE_SIZE ;
q [ *rear ] = item ;
( *count ) ++ ;
}
/*************** delete_cq ( ) **************/
int delete_cq (int *front , int *count , int q[ ] ) {
int item ;
/******** check for underflow *********/
if ( *count == 0 )
return -1 ;
item = [ *front ] ;
*front = ( *front + 1 ) % QUE_SIZE ;
*count - = 1 ;
return item ;
}
/*************** display_q ( ) **************/
void display_cq (int front , int count , int q[ ] ) {
register unsigned int i ;
/****** End of Program to implement Circular Queue operations by passing parameters *****/
/******* **Program to implement Circular Queue operations using Dynamic Array ********/
#define MALLOC ( ptr , n , type ) /** To allocate memory for One or More items of any data type **/ \
ptr = ( type * ) malloc ( n * sizeof ( type ) ) ; \
if ( ptr == NULL ) { \
printf ( “\n INSUFFICIENT MEMORY!”) ; \
getch () ; \
exit ( 0 ) ; \
}
#define REALLOC ( ptr , n , type ) /** To Reallocate memory for One or More items of any data type **/ \
ptr = ( type * ) realloc ( n * sizeof ( type ) ) ; \
if ( ptr == NULL ) { \
printf ( “\n INSUFFICIENT MEMORY!”) ; \
getch () ; \
exit ( 0 ) ; \
}
int QUE_SIZE = 1 ; /* Global Declaration not as #define since we are varying its value.*/
void inset_cq ( int item , int *rear , int *q , int *count) ;
int delete_cq ( int *front , int *count , int q[ ] ) ;
void display_cq ( int front , int count , int q[ ] ) ;
void main ( ) {
int ch , item , front , rear , count , *q ;
/**** Intially Queue is Empty ****/
front = 0 ; // front end of queue
rear = -1 ; // rear end of queue
count = 0 ; // empty queue
MALLOC ( q , 1 , int ) ;
for ( ; ; ) {
printf ( “ \n 1. Insert \t 2. Delete \t 3. Display 4. Exit \n Enter Your Choice :\t “ ) ;
scanf ( “%d” , &ch ) ;
switch ( ch ) {
case 1 : printf ( “Enter the item to be inserted :\t” ) ;
scanf ( “%d”, &item ) ;
inset_cq ( item , &rear , q , &count ) ;
break ;
case 2 : item = delete_cq ( &front , &count , q );
if ( item == -1 )
printf ( “ Queue is empty “ ) ;
else
printf ( “Deleted item :\t%d” , item ) ;