Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
348 views

Stack and Queue

Stack is an abstract data type that follows the LIFO (last-in, first-out) principle. Elements are inserted and removed from the top of the stack. Common operations on a stack include push to add an element and pop to remove the top element. Stacks have many applications, such as reversing a word by pushing and popping letters, and parsing expressions by converting them to postfix notation. Stacks can be implemented using arrays or linked lists, with push and pop operations taking constant time.

Uploaded by

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

Stack and Queue

Stack is an abstract data type that follows the LIFO (last-in, first-out) principle. Elements are inserted and removed from the top of the stack. Common operations on a stack include push to add an element and pop to remove the top element. Stacks have many applications, such as reversing a word by pushing and popping letters, and parsing expressions by converting them to postfix notation. Stacks can be implemented using arrays or linked lists, with push and pop operations taking constant time.

Uploaded by

shemse
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 61

Stacks

Stack is an abstract data type with a bounded (predefined) capacity. It is a simple data structure
that allows adding and removing elements in a particular order. Every time an element is added,
it goes on the top of the stack, the only element that can be removed is the element that was at
the top of the stack, just like a pile of objects.

Basic features of Stack

1. Stack is an ordered list of similar data type.

2. Stack is a LIFO structure. (Last in First out).

3. push() function is used to insert new elements into the Stack and pop() function is used to

delete an element from the stack. Both insertion and deletion are allowed at only one end of

Stack called Top.

4. Stack is said to be in Overflow state when it is completely full and is said to be

in Underflow state if it is completely empty.

Applications of Stack
The simplest application of a stack is to reverse a word. You push a given word to stack - letter
by letter - and then pop letters from the stack.
There are other uses also like : Parsing, Expression Conversion(Infix to Postfix, Postfix to
Prefix etc) and many more.

Implementation of Stack
Stack can be easily implemented using an Array or a Linked List. Arrays are quick, but are
limited in size and Linked List requires overhead to allocate, link, unlink, and deallocate, but is
not limited in size. Here we will implement Stack using array.

Algorithm for PUSH operation

1. Check if the stack is full or not.

2. If the stack is full,then print error of overflow and exit the program.

3. If the stack is not full,then increment the top and add the element .

Algorithm for POP operation

1. Check if the stack is empty or not.

2. If the stack is empty, then print error of underflow and exit the program.

3. If the stack is not empty, then print the element at the top and decrement the top.

/* Below program is written in C++ language */

Class Stack

{
int top;

public:

int a[10]; //Maximum size of Stack

Stack()

top = -1;

};

void Stack::push(int x)

if( top >= 10)

cout << "Stack Overflow";

else

a[++top] = x;

cout << "Element Inserted";

int Stack::pop()

if(top < 0)

cout << "Stack Underflow";

return 0;

else

int d = a[top--];

return d;

}
}

void Stack::isEmpty()

if(top < 0)

cout << "Stack is empty";

else

cout << "Stack is not empty";

Position of Top Status of Stack

-1 Stack is Empty

0 Only one element in Stack

N-1 Stack is Full

N Overflow state of Stack

Analysis of Stacks
Below mentioned are the time complexities for various operations that can be performed on the
Stack data structure.

 Push Operation : O(1)


 Pop Operation : O(1)

 Top Operation : O(1)

 Search Operation : O(n)

Queue Data Structures


Queue is also an abstract data type or a linear data structure, in which the first
element is inserted from one end called REAR(also called tail), and the deletion of
existing element takes place from the other end called as FRONT(also called head).
This makes queue as FIFO(First in First Out) data structure, which means that
element inserted first will also be removed first.
The process to add an element into queue is called Enqueue and the process of
removal of an element from queue is called Dequeue.

Basic features of Queue

1. Like Stack, Queue is also an ordered list of elements of similar data types.

2. Queue is a FIFO( First in First Out ) structure.


3. Once a new element is inserted into the Queue, all the elements inserted before

the new element in the queue must be removed, to remove the new element.

4. peek( ) function is oftenly used to return the value of first element without

dequeuing it.

Applications of Queue
Queue, as the name suggests is used whenever we need to manage any group of
objects in an order in which the first one coming in, also gets out first while the
others wait for their turn, like in the following scenarios :

1. Serving requests on a single shared resource, like a printer, CPU task

scheduling etc.

2. In real life scenario, Call Center phone systems uses Queues to hold people

calling them in an order, until a service representative is free.

3. Handling of interrupts in real-time systems. The interrupts are handled in the

same order as they arrive i.e First come first served.

Implementation of Queue
Queue can be implemented using an Array, Stack or Linked List. The easiest way of
implementing a queue is by using an Array. Initially the head(FRONT) and
the tail(REAR) of the queue points at the first index of the array (starting the index of
array from 0). As we add elements to the queue, the tail keeps on moving ahead,
always pointing to the position where the next element will be inserted, while the
head remains at the first index.
When we remove an element from Queue, we can follow two possible approaches
(mentioned [A] and [B] in above diagram). In [A] approach, we remove the element
at head position, and then one by one shift all the other elements in forward
position. In approach [B] we remove the element from headposition and then
move head to the next position.
In approach [A] there is an overhead of shifting the elements one position forward
every time we remove the first element. In approach [B] there is no such overhead,
but whenever we move head one position ahead, after removal of first element, the
size on Queue is reduced by one space each time.

Algorithm for ENQUEUE operation


1. Check if the queue is full or not.

2. If the queue is full, then print overflow error and exit the program.

3. If the queue is not full, then increment the tail and add the element.

Algorithm for DEQUEUE operation

1. Check if the queue is empty or not.

2. If the queue is empty, then print underflow error and exit the program.

3. If the queue is not empty, then print the element at the head and increment the
head.

/* Below program is written in C++ language */

#define SIZE 100

class Queue

int a[100];

int rear; //same as tail

int front; //same as head

public:

Queue()

rear = front = -1;

void enqueue(int x); //declaring enqueue, dequeue and display functions

int dequeue();

void display();

void Queue :: enqueue(int x)

if( rear = SIZE-1)


{

cout << "Queue is full";

else

a[++rear] = x;

int queue :: dequeue()

return a[++front]; //following approach [B], explained above

void queue :: display()

int i;

for( i = front; i <= rear; i++)

cout << a[i];

To implement approach [A], you simply need to change the dequeue method, and
include a for loop which will shift all the remaining elements one position.
return a[0]; //returning first element

for (i = 0; i < tail-1; i++) //shifting all other elements

a[i]= a[i+1];

tail--;

Analysis of Queue
 Enqueue : O(1)

 Dequeue : O(1)

 Size : O(1)

 Queue Data Structure using Stack


 A Queue is defined by its property of FIFO, which means First in First Out, i.e
the element which is added first is taken out first. Hence we can implement a
Queue using Stack for storage instead of array.
 For performing enqueue we require only one stack as we can
directly push data into stack, but to perform dequeue we will require two
Stacks, because we need to follow queue's FIFO property and if we
directly pop any data element out of Stack, it will follow LIFO approach(Last
in First Out).

 Implementation of Queue using Stacks
 In all we will require two Stacks, we will call them InStack and OutStack.
 class Queue {
 public:
 Stack S1, S2;
 //defining methods

 void enqueue(int x);

 int dequeue();
 }

 We know that, Stack is a data structure, in which data can be added


using push() method and data can be deleted using pop() method. To learn
about Stack, follow the link : Stack Data Structure

 Adding Data to Queue


 As our Queue has Stack for data storage in place of arrays, hence we will be
adding data to Stack, which can be done using the push() method, hence :
 void Queue :: enqueue(int x) {
 S1.push(x);
 }

 Removing Data from Queue


 When we say remove data from Queue, it always means taking out the First
element first and so on, as we have to follow the FIFO approach. But if we
simply perform S1.pop() in our dequeue method, then it will remove the Last
element first. So what to do now?


 int Queue :: dequeue() {
 while(S1.isEmpty()) {
 x = S1.pop();
 S2.push();
 }

 //removing the element
 x = S2.pop();

 while(!S2.isEmpty()) {
 x = S2.pop();
 S1.push(x);
 }

 return x;
 }

Stack ADT

What is a Stack?
Stack is a linear data structure in which the insertion and deletion
operations are performed at only one end. In a stack, adding and removing
of elements are performed at single position which is known as "top". That
means, new element is added at top of the stack and an element is removed
from the top of the stack. In stack, the insertion and deletion operations are
performed based on LIFO (Last In First Out) principle.
In a stack, the insertion operation is performed using a function
called "push" and deletion operation is performed using a function
called "pop".

In the figure, PUSH and POP operations are performed at top position in the
stack. That means, both the insertion and deletion operations are
performed at one end (i.e., at Top)

A stack data structure can be defined as follows...

Stack is a linear data structure in which the operations are performed


based on LIFO principle.

Stack can also be defined as

"A Collection of similar data items in which both insertion and deletion
operations are performed based on LIFO principle".

Example
If we want to create a stack by inserting 10,45,12,16,35 and 50. Then 10
becomes the bottom most element and 50 is the top most element. Top is at
50 as shown in the image below...
Operations on a Stack
The following operations are performed on the stack...

1. Push (To insert an element on to the stack)


2. Pop (To delete an element from the stack)
3. Display (To display elements of the stack)

Stack data structure can be implement in two ways. They are as follows...

1. Using Array
2. Using Linked List

When stack is implemented using array, that stack can organize only limited
number of elements. When stack is implemented using linked list, that stack
can organize unlimited number of elements.

Stack Using Array

A stack data structure can be implemented using one dimensional array. But
stack implemented using array, can store only fixed number of data values.
This implementation is very simple, just define a one dimensional array of
specific size and insert or delete the values into that array by using LIFO
principle with the help of a variable 'top'. Initially top is set to -1.
Whenever we want to insert a value into the stack, increment the top value
by one and then insert. Whenever we want to delete a value from the stack,
then delete the top value and decrement the top value by one.

Stack Operations using Array


A stack can be implemented using array as follows...

Before implementing actual operations, first follow the below steps to


create an empty stack.
 Step 1: Include all the header files which are used in the program and
define a constant 'SIZE' with specific value.
 Step 2: Declare all the functions used in stack implementation.
 Step 3: Create a one dimensional array with fixed size (int
stack[SIZE])
 Step 4: Define a integer variable 'top' and initialize with '-1'. (int top
= -1)
 Step 5: In main method display menu with list of operations and make
suitable function calls to perform operation selected by the user on
the stack.

push(value) - Inserting value into the stack


In a stack, push() is a function used to insert an element into the stack. In a
stack, the new element is always inserted at top position. Push function
takes one integer value as parameter and inserts that value into the stack.
We can use the following steps to push an element on to the stack...

 Step 1: Check whether stack is FULL. (top == SIZE-1)


 Step 2: If it is FULL, then display "Stack is FULL!!! Insertion is not
possible!!!" and terminate the function.
 Step 3: If it is NOT FULL, then increment top value by one (top++)
and set stack[top] to value (stack[top] = value).

pop() - Delete a value from the Stack


In a stack, pop() is a function used to delete an element from the stack. In a
stack, the element is always deleted from top position. Pop function does
not take any value as parameter. We can use the following steps to pop an
element from the stack...
 Step 1: Check whether stack is EMPTY. (top == -1)
 Step 2: If it is EMPTY, then display "Stack is EMPTY!!! Deletion is not
possible!!!" and terminate the function.
 Step 3: If it is NOT EMPTY, then delete stack[top] and
decrement top value by one (top--).

display() - Displays the elements of a Stack


We can use the following steps to display the elements of a stack...

 Step 1: Check whether stack is EMPTY. (top == -1)


 Step 2: If it is EMPTY, then display "Stack is EMPTY!!!" and terminate
the function.
 Step 3: If it is NOT EMPTY, then define a variable 'i' and initialize with
top. Display stack[i] value and decrement i value by one (i--).
 Step 3: Repeat above step until i value becomes '0'.

Complete Program in C Programming


Language
#include<stdio.h>
#include<conio.h>

#define SIZE 10

void push(int);
void pop();
void display();

int stack[SIZE], top = -1;

void main()
{
int value, choice;
clrscr();
while(1){
printf("\n\n***** MENU *****\n");
printf("1. Push\n2. Pop\n3. Display\n4. Exit");
printf("\nEnter your choice: ");
scanf("%d",&choice);
switch(choice){
case 1: printf("Enter the value to be insert: ");
scanf("%d",&value);
push(value);
break;
case 2: pop();
break;
case 3: display();
break;
case 4: exit(0);
default: printf("\nWrong selection!!! Try again!!!");
}
}
}
void push(int value){
if(top == SIZE-1)
printf("\nStack is Full!!! Insertion is not possible!!!");
else{
top++;
stack[top] = value;
printf("\nInsertion success!!!");
}
}
void pop(){
if(top == -1)
printf("\nStack is Empty!!! Deletion is not possible!!!");
else{
printf("\nDeleted : %d", stack[top]);
top--;
}
}
void display(){
if(top == -1)
printf("\nStack is Empty!!!");
else{
int i;
printf("\nStack elements are:\n");
for(i=top; i>=0; i--)
printf("%d\n",stack[i]);
}
}

Output
Stack using Linked List

The major problem with the stack implemented using array is, it works only
for fixed number of data values. That means the amount of data must be
specified at the beginning of the implementation itself. Stack implemented
using array is not suitable, when we don't know the size of data which we
are going to use. A stack data structure can be implemented by using linked
list data structure. The stack implemented using linked list can work for
unlimited number of values. That means, stack implemented using linked
list works for variable size of data. So, there is no need to fix the size at the
beginning of the implementation. The Stack implemented using linked list
can organize as many data values as we want.

In linked list implementation of a stack, every new element is inserted as


'top' element. That means every newly inserted element is pointed by 'top'.
Whenever we want to remove an element from the stack, simply remove the
node which is pointed by 'top' by moving 'top' to its next node in the list.
The next field of the first element must be always NULL.
Example

In above example, the last inserted node is 99 and the first inserted node is
25. The order of elements inserted is 25, 32,50 and 99.

Operations
To implement stack using linked list, we need to set the following things
before implementing actual operations.

 Step 1: Include all the header files which are used in the program.
And declare all the user defined functions.
 Step 2: Define a 'Node' structure with two members data and next.
 Step 3: Define a Node pointer 'top' and set it to NULL.
 Step 4: Implement the main method by displaying Menu with list of
operations and make suitable function calls in the mainmethod.

push(value) - Inserting an element into the Stack


We can use the following steps to insert a new node into the stack...
 Step 1: Create a newNode with given value.
 Step 2: Check whether stack is Empty (top == NULL)
 Step 3: If it is Empty, then set newNode → next = NULL.
 Step 4: If it is Not Empty, then set newNode → next = top.
 Step 5: Finally, set top = newNode.

pop() - Deleting an Element from a Stack


We can use the following steps to delete a node from the stack...

 Step 1: Check whether stack is Empty (top == NULL).


 Step 2: If it is Empty, then display "Stack is Empty!!! Deletion is not
possible!!!" and terminate the function
 Step 3: If it is Not Empty, then define a Node pointer 'temp' and set it
to 'top'.
 Step 4: Then set 'top = top → next'.
 Step 7: Finally, delete 'temp' (free(temp)).

display() - Displaying stack of elements


We can use the following steps to display the elements (nodes) of a stack...

 Step 1: Check whether stack is Empty (top == NULL).


 Step 2: If it is Empty, then display 'Stack is Empty!!!' and terminate
the function.
 Step 3: If it is Not Empty, then define a Node pointer 'temp' and
initialize with top.
 Step 4: Display 'temp → data --->' and move it to the next node.
Repeat the same until temp reaches to the first node in the stack
(temp → next != NULL).
 Step 4: Finally! Display 'temp → data ---> NULL'.

Program for Stack Using Linked List


#include<stdio.h>
#include<conio.h>

struct Node
{
int data;
struct Node *next;
}*top = NULL;

void push(int);
void pop();
void display();

void main()
{
int choice, value;
clrscr();
printf("\n:: Stack using Linked List ::\n");
while(1){
printf("\n****** MENU ******\n");
printf("1. Push\n2. Pop\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);
push(value);
break;
case 2: pop(); break;
case 3: display(); break;
case 4: exit(0);
default: printf("\nWrong selection!!! Please try again!!!\n");
}
}
}
void push(int value)
{
struct Node *newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = value;
if(top == NULL)
newNode->next = NULL;
else
newNode->next = top;
top = newNode;
printf("\nInsertion is Success!!!\n");
}
void pop()
{
if(top == NULL)
printf("\nStack is Empty!!!\n");
else{
struct Node *temp = top;
printf("\nDeleted element: %d", temp->data);
top = temp->next;
free(temp);
}
}
void display()
{
if(top == NULL)
printf("\nStack is Empty!!!\n");
else{
struct Node *temp = top;
while(temp->next != NULL){
printf("%d--->",temp->data);
temp = temp -> next;
}
printf("%d--->NULL",temp->data);
}
}

Output
Expressions

What is an Expression?
In any programming language, if we want to perform any calculation or to
frame a condition etc., we use a set of symbols to perform the task. These
set of symbols makes an expression.

An expression can be defined as follows...

An expression is a collection of operators and operands that represents


a specific value.

In above definition, operator is a symbol which performs a particular task


like arithmetic operation or logical operation or conditional operation etc.,
Operands are the values on which the operators can perform the task. Here
operand can be a direct value or variable or address of memory location.

Expression Types
Based on the operator position, expressions are divided into THREE types.
They are as follows...

1. Infix Expression
2. Postfix Expression
3. Prefix Expression

Infix Expression
In infix expression, operator is used in between operands.

The general structure of an Infix expression is as follows...

Operand1 Operator Operand2

Example

Postfix Expression
In postfix expression, operator is used after operands. We can say that
"Operator follows the Operands".
The general structure of Postfix expression is as follows...

Operand1 Operand2 Operator

Example

Prefix Expression
In prefix expression, operator is used before operands. We can say that
"Operands follows the Operator".

The general structure of Prefix expression is as follows...

Operator Operand1 Operand2

Example
Any expression can be represented using the above three different types of
expressions. And we can convert an expression from one form to another
form like Infix to Postfix, Infix to Prefix, Prefix to Postfix and vice versa.

Expression Conversion

Any expression can be represented using three types of expressions (Infix,


Postfix and Prefix). We can also convert one type of expression to another
type of expression like Infix to Postfix, Infix to Prefix, Postfix to Prefix and
vice versa.

To convert any Infix expression into Postfix or Prefix expression we can use
the following procedure...

1. Find all the operators in the given Infix Expression.


2. Find the order of operators evaluated according to their Operator
precedence.
3. Convert each operator into required type of expression (Postfix or
Prefix) in the same order.

Example
Consider the following Infix Expression to be converted into Postfix
Expression...
D=A+B*C
 Step 1: The Operators in the given Infix Expression : = , + , *
 Step 2: The Order of Operators according to their preference : * , + ,
=
 Step 3: Now, convert the first operator * ----- D = A + B C *
 Step 4: Convert the next operator + ----- D = A BC* +
 Step 5: Convert the next operator = ----- D ABC*+ =

Finally, given Infix Expression is converted into Postfix Expression as


follows...

DABC*+=
Infix to Postfix Conversion using Stack
Data Structure
To convert Infix Expression into Postfix Expression using a stack data
structure, We can use the following steps...

1. Read all the symbols one by one from left to right in the given
Infix Expression.
2. If the reading symbol is operand, then directly print it to the
result (Output).
3. If the reading symbol is left parenthesis '(', then Push it on to the
Stack.
4. If the reading symbol is right parenthesis ')', then Pop all the
contents of stack until respective left parenthesis is poped and
print each poped symbol to the result.
5. If the reading symbol is operator (+ , - , * , / etc.,), then Push it
on to the Stack. However, first pop the operators which are
already on the stack that have higher or equal precedence than
current operator and print them to the result.
Example
Consider the following Infix Expression...

(A+B)*(C-D)
The given infix expression can be converted into postfix expression using
Stack data Structure as follows...
The final Postfix Expression is as follows...

AB+CD-*

Postfix Expression Evaluation

A postfix expression is a collection of operators and operands in which the


operator is placed after the operands. That means, in a postfix expression
the operator follows the operands.

Postfix Expression has following general structure...

Operand1 Operand2 Operator


Example

Postfix Expression Evaluation using Stack


Data Structure
A postfix expression can be evaluated using the Stack data structure. To
evaluate a postfix expression using Stack data structure we can use the
following steps...

1. Read all the symbols one by one from left to right in the given
Postfix Expression
2. If the reading symbol is operand, then push it on to the Stack.
3. If the reading symbol is operator (+ , - , * , / etc.,), then perform
TWO pop operations and store the two popped oparands in two
different variables (operand1 and operand2). Then perform
reading symbol operation using operand1 and operand2 and push
result back on to the Stack.
4. Finally! perform a pop operation and display the popped value as
final result.

Example
Consider the following Expression...
Queue ADT

What is a Queue?
Queue is a linear data structure in which the insertion and deletion
operations are performed at two different ends. In a queue data structure,
adding and removing of elements are performed at two different positions.
The insertion is performed at one end and deletion is performed at other
end. In a queue data structure, the insertion operation is performed at a
position which is known as 'rear' and the deletion operation is performed at
a position which is known as 'front'. In queue data structure, the insertion
and deletion operations are performed based on FIFO (First In First
Out) principle.

In a queue data structure, the insertion operation is performed using a


function called "enQueue()" and deletion operation is performed using a
function called "deQueue()".

Queue data structure can be defined as follows...

Queue data structure is a linear data structure in which the operations


are performed based on FIFO principle.

A queue can also be defined as


"Queue data structure is a collection of similar data items in which
insertion and deletion operations are performed based on FIFO
principle".

Example
Queue after inserting 25, 30, 51, 60 and 85.

Operations on a Queue
The following operations are performed on a queue data structure...

1. enQueue(value) - (To insert an element into the queue)


2. deQueue() - (To delete an element from the queue)
3. display() - (To display the elements of the queue)

Queue data structure can be implemented in two ways. They are as


follows...

1. Using Array
2. Using Linked List

When a queue is implemented using array, that queue can organize only
limited number of elements. When a queue is implemented using linked list,
that queue can organize unlimited number of elements.

Queue Using Array


A queue data structure can be implemented using one dimensional array.
But, queue implemented using array can store only fixed number of data
values. The implementation of queue data structure using array is very
simple, just define a one dimensional array of specific size and insert or
delete the values into that array by using FIFO (First In First Out)
principle with the help of variables 'front' and 'rear'. Initially both 'front'
and 'rear' are set to -1. Whenever, we want to insert a new value into the
queue, increment 'rear' value by one and then insert at that position.
Whenever we want to delete a value from the queue, then increment 'front'
value by one and then display the value at 'front' position as deleted
element.

Queue Operations using Array


Queue data structure using array can be implemented as follows...

Before we implement actual operations, first follow the below steps to


create an empty queue.

 Step 1: Include all the header files which are used in the program
and define a constant 'SIZE' with specific value.
 Step 2: Declare all the user defined functions which are used in
queue implementation.
 Step 3: Create a one dimensional array with above defined SIZE (int
queue[SIZE])
 Step 4: Define two integer variables 'front' and 'rear' and initialize
both with '-1'. (int front = -1, rear = -1)
 Step 5: Then implement main method by displaying menu of
operations list and make suitable function calls to perform operation
selected by the user on queue.
enQueue(value) - Inserting value into the queue
In a queue data structure, enQueue() is a function used to insert a new
element into the queue. In a queue, the new element is always inserted
at rear position. The enQueue() function takes one integer value as
parameter and inserts that value into the queue. We can use the following
steps to insert an element into the queue...

 Step 1: Check whether queue is FULL. (rear == SIZE-1)


 Step 2: If it is FULL, then display "Queue is FULL!!! Insertion is not
possible!!!" and terminate the function.
 Step 3: If it is NOT FULL, then increment rear value by one (rear++)
and set queue[rear] = value.

deQueue() - Deleting a value from the Queue


In a queue data structure, deQueue() is a function used to delete an
element from the queue. In a queue, the element is always deleted
from front position. The deQueue() function does not take any value as
parameter. We can use the following steps to delete an element from the
queue...

 Step 1: Check whether queue is EMPTY. (front == rear)


 Step 2: If it is EMPTY, then display "Queue is EMPTY!!! Deletion is
not possible!!!" and terminate the function.
 Step 3: If it is NOT EMPTY, then increment the front value by one
(front ++). Then display queue[front] as deleted element. Then
check whether both front and rear are equal (front == rear), if
it TRUE, then set both front and rear to '-1' (front = rear = -1).

display() - Displays the elements of a Queue


We can use the following steps to display the elements of a queue...

 Step 1: Check whether queue is EMPTY. (front == rear)


 Step 2: If it is EMPTY, then display "Queue is EMPTY!!!" and
terminate the function.
 Step 3: If it is NOT EMPTY, then define an integer variable 'i' and set
'i = front+1'.
 Step 3: Display 'queue[i]' value and increment 'i' value by one (i++).
Repeat the same until 'i' value is equal to rear (i <= rear)

Program to implement Queue using Array


#include<stdio.h>
#include<conio.h>
#define SIZE 10

void enQueue(int);
void deQueue();
void display();

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

void main()
{
int value, choice;
clrscr();
while(1){
printf("\n\n***** MENU *****\n");
printf("1. Insertion\n2. Deletion\n3. Display\n4. Exit");
printf("\nEnter your choice: ");
scanf("%d",&choice);
switch(choice){
case 1: printf("Enter the value to be insert: ");
scanf("%d",&value);
enQueue(value);
break;
case 2: deQueue();
break;
case 3: display();
break;
case 4: exit(0);
default: printf("\nWrong selection!!! Try again!!!");
}
}
}
void enQueue(int value){
if(rear == SIZE-1)
printf("\nQueue is Full!!! Insertion is not possible!!!");
else{
if(front == -1)
front = 0;
rear++;
queue[rear] = value;
printf("\nInsertion success!!!");
}
}
void deQueue(){
if(front == rear)
printf("\nQueue is Empty!!! Deletion is not possible!!!");
else{
printf("\nDeleted : %d", queue[front]);
front++;
if(front == rear)
front = rear = -1;
}
}
void display(){
if(rear == -1)
printf("\nQueue is Empty!!!");
else{
int i;
printf("\nQueue elements are:\n");
for(i=front; i<=rear; i++)
printf("%d\t",queue[i]);
}
}

Output

Queue using Linked List


The major problem with the queue implemented using array is, It will work
for only fixed number of data. That means, the amount of data must be
specified in the beginning itself. Queue using array is not suitable when we
don't know the size of data which we are going to use. A queue data
structure can be implemented using linked list data structure. The queue
which is implemented using linked list can work for unlimited number of
values. That means, queue using linked list can work for variable size of
data (No need to fix the size at beginning of the implementation). The
Queue implemented using linked list can organize as many data values as we
want.

In linked list implementation of a queue, the last inserted node is always


pointed by 'rear' and the first node is always pointed by 'front'.

Example

In above example, the last inserted node is 50 and it is pointed by 'rear' and
the first inserted node is 10 and it is pointed by 'front'. The order of
elements inserted is 10, 15, 22 and 50.

Operations
To implement queue using linked list, we need to set the following things
before implementing actual operations.

 Step 1: Include all the header files which are used in the program.
And declare all the user defined functions.
 Step 2: Define a 'Node' structure with two members data and next.
 Step 3: Define two Node pointers 'front' and 'rear' and set both
to NULL.
 Step 4: Implement the main method by displaying Menu of list of
operations and make suitable function calls in the main method to
perform user selected operation.

enQueue(value) - Inserting an element into the


Queue
We can use the following steps to insert a new node into the queue...

 Step 1: Create a newNode with given value and set 'newNode →


next' to NULL.
 Step 2: Check whether queue is Empty (rear == NULL)
 Step 3: If it is Empty then,
set front = newNode and rear = newNode.
 Step 4: If it is Not Empty then, set rear →
next = newNode and rear = newNode.

deQueue() - Deleting an Element from Queue


We can use the following steps to delete a node from the queue...

 Step 1: Check whether queue is Empty (front == NULL).


 Step 2: If it is Empty, then display "Queue is Empty!!! Deletion is
not possible!!!" and terminate from the function
 Step 3: If it is Not Empty then, define a Node pointer 'temp' and set
it to 'front'.
 Step 4: Then set 'front = front → next' and delete 'temp'
(free(temp)).

display() - Displaying the elements of Queue


We can use the following steps to display the elements (nodes) of a queue...

 Step 1: Check whether queue is Empty (front == NULL).


 Step 2: If it is Empty then, display 'Queue is Empty!!!' and
terminate the function.
 Step 3: If it is Not Empty then, define a Node pointer 'temp' and
initialize with front.
 Step 4: Display 'temp → data --->' and move it to the next node.
Repeat the same until 'temp' reaches to 'rear' (temp →
next != NULL).
 Step 4: Finally! Display 'temp → data ---> NULL'.

Program for Queue Using Linked List


#include<stdio.h>
#include<conio.h>

struct Node
{
int data;
struct Node *next;
}*front = NULL,*rear = NULL;

void insert(int);
void delete();
void display();

void main()
{
int choice, value;
clrscr();
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);
insert(value);
break;
case 2: delete(); break;
case 3: display(); break;
case 4: exit(0);
default: printf("\nWrong selection!!! Please try again!!!\n");
}
}
}
void insert(int value)
{
struct Node *newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = value;
newNode -> next = NULL;
if(front == NULL)
front = rear = newNode;
else{
rear -> next = newNode;
rear = newNode;
}
printf("\nInsertion is Success!!!\n");
}
void delete()
{
if(front == NULL)
printf("\nQueue is Empty!!!\n");
else{
struct Node *temp = front;
front = front -> next;
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->next != NULL){
printf("%d--->",temp->data);
temp = temp -> next;
}
printf("%d--->NULL\n",temp->data);
}
}

Output
Circular Queue
In a normal Queue Data Structure, we can insert elements until queue
becomes full. But once if queue becomes full, we can not insert the next
element until all the elements are deleted from the queue. For example
consider the queue below...

After inserting all the elements into the queue.

Now consider the following situation after deleting three elements from the
queue...

This situation also says that Queue is Full and we can not insert the new
element because, 'rear' is still at last position. In above situation, even
though we have empty positions in the queue we can not make use of them
to insert new element. This is the major problem in normal queue data
structure. To overcome this problem we use circular queue data structure.

What is Circular Queue?


A Circular Queue can be defined as follows...
Circular Queue is a linear data structure in which the operations are
performed based on FIFO (First In First Out) principle and the last
position is connected back to the first position to make a circle.

Graphical representation of a circular queue is as follows...

Implementation of Circular Queue


To implement a circular queue data structure using array, we first perform
the following steps before we implement actual operations.

 Step 1: Include all the header files which are used in the program
and define a constant 'SIZE' with specific value.
 Step 2: Declare all user defined functions used in circular queue
implementation.
 Step 3: Create a one dimensional array with above defined SIZE (int
cQueue[SIZE])
 Step 4: Define two integer variables 'front' and 'rear' and initialize
both with '-1'. (int front = -1, rear = -1)
 Step 5: Implement main method by displaying menu of operations list
and make suitable function calls to perform operation selected by the
user on circular queue.

enQueue(value) - Inserting value into the


Circular Queue
In a circular queue, enQueue() is a function which is used to insert an
element into the circular queue. In a circular queue, the new element is
always inserted at rear position. The enQueue() function takes one integer
value as parameter and inserts that value into the circular queue. We can
use the following steps to insert an element into the circular queue...

 Step 1: Check whether queue is FULL. ((rear == SIZE-1 && front ==


0) || (front == rear+1))
 Step 2: If it is FULL, then display "Queue is FULL!!! Insertion is not
possible!!!" and terminate the function.
 Step 3: If it is NOT FULL, then check rear == SIZE - 1 && front !=
0 if it is TRUE, then set rear = -1.
 Step 4: Increment rear value by one (rear++),
set queue[rear] = value and check 'front == -1' if it is TRUE, then
set front = 0.

deQueue() - Deleting a value from the Circular


Queue
In a circular queue, deQueue() is a function used to delete an element from
the circular queue. In a circular queue, the element is always deleted
from front position. The deQueue() function doesn't take any value as
parameter. We can use the following steps to delete an element from the
circular queue...

 Step 1: Check whether queue is EMPTY. (front == -1 && rear == -1)


 Step 2: If it is EMPTY, then display "Queue is EMPTY!!! Deletion is
not possible!!!" and terminate the function.
 Step 3: If it is NOT EMPTY, then display queue[front] as deleted
element and increment the front value by one (front ++). Then check
whether front == SIZE, if it is TRUE, then set front = 0. Then check
whether both front - 1 and rear are equal (front -1 == rear), if
it TRUE, then set both front and rear to '-1' (front = rear = -1).

display() - Displays the elements of a Circular


Queue
We can use the following steps to display the elements of a circular queue...

 Step 1: Check whether queue is EMPTY. (front == -1)


 Step 2: If it is EMPTY, then display "Queue is EMPTY!!!" and
terminate the function.
 Step 3: If it is NOT EMPTY, then define an integer variable 'i' and set
'i = front'.
 Step 4: Check whether 'front <= rear', if it is TRUE, then display
'queue[i]' value and increment 'i' value by one (i++). Repeat the same
until 'i <= rear' becomes FALSE.
 Step 5: If 'front <= rear' is FALSE, then display 'queue[i]' value and
increment 'i' value by one (i++). Repeat the same until'i <= SIZE - 1'
becomes FALSE.
 Step 6: Set i to 0.
 Step 7: Again display 'cQueue[i]' value and increment i value by one
(i++). Repeat the same until 'i <= rear' becomes FALSE.

Program to implement Queue using Array


#include<stdio.h>
#include<conio.h>
#define SIZE 5

void enQueue(int);
void deQueue();
void display();

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

void main()
{
int choice, value;
clrscr();
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("\nEnter the value to be insert: ");
scanf("%d",&value);
enQueue(value);
break;
case 2: deQueue();
break;
case 3: display();
break;
case 4: exit(0);
default: printf("\nPlease select the correct choice!!!\n");
}
}
}
void enQueue(int value)
{
if((front == 0 && rear == SIZE - 1) || (front == rear+1))
printf("\nCircular Queue is Full! Insertion not possible!!!\n");
else{
if(rear == SIZE-1 && front != 0)
rear = -1;
cQueue[++rear] = value;
printf("\nInsertion Success!!!\n");
if(front == -1)
front = 0;
}
}
void deQueue()
{
if(front == -1 && rear == -1)
printf("\nCircular Queue is Empty! Deletion is not possible!!!\n");
else{
printf("\nDeleted element : %d\n",cQueue[front++]);
if(front == SIZE)
front = 0;
if(front-1 == rear)
front = rear = -1;
}
}
void display()
{
if(front == -1)
printf("\nCircular Queue is Empty!!!\n");
else{
int i = front;
printf("\nCircular Queue Elements are : \n");
if(front <= rear){
while(i <= rear)
printf("%d\t",cQueue[i++]);
}
else{
while(i <= SIZE - 1)
printf("%d\t", cQueue[i++]);
i = 0;
while(i <= rear)
printf("%d\t",cQueue[i++]);
}
}
}

Output
Priority Queue

In 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 situations.

Consider a networking application where server has to respond for requests


from multiple clients using queue data structure. Assume four requests
arrived to the queue in the order of 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.
Queue is as follows...
Now, check waiting time for each request to be complete.

1. R1 : 20 units of time
2. R2 : 22 units of time (R2 must wait till R1 complete - 20 units and
R2 itself requeres 2 units. Total 22 units)
3. R3 : 32 units of time (R3 must wait till R2 complete - 22 units and
R3 itself requeres 10 units. Total 32 units)
4. R4 : 37 units of time (R4 must wait till R3 complete - 35 units and
R4 itself requeres 5 units. Total 37 units)

Here, 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. That means, first we serve R2 which has
minimum time required (2) then serve R4 which has second minimum time
required (5) then serve R3 which has third minimum time required (10) and
finnaly R1 which has maximum time required (20).

Now, check waiting time for each request to be complete.

1. R2 : 2 units of time
2. R4 : 7 units of time (R4 must wait till R2 complete 2 units and R4
itself requeres 5 units. Total 7 units)
3. R3 : 17 units of time (R3 must wait till R4 complete 7 units and R3
itself requeres 10 units. Total 17 units)
4. R1 : 37 units of time (R1 must wait till R3 complete 17 units and
R1 itself requeres 20 units. Total 37 units)

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

From above two situations, it is very clear that, by using 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 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 max priority queue, elements are inserted in the order in which they
arrive the queue and always maximum value is removed first from the
queue. For example assume that we insert in 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.

Max Priority Queue Representations


There are 6 representations of max priority queue.
1. Using an Unordered Array (Dynamic Array)
2. Using an Unordered Array (Dynamic Array) with the index of the
maximum value
3. Using an Array (Dynamic Array) in Decreasing Order
4. Using an Array (Dynamic Array) in Increasing Order
5. Using Linked List in Increasing Order
6. Using Unordered Linked List with reference to node with the
maximum value

#1. Using an Unordered Array (Dynamic Array)


In this representation elements are inserted according to their arrival order
and maximum element is deleted first from max priority queue.

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

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


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

insert() - New element is added at the end of the queue. This operation
requires O(1) time complexity that means constant time.

findMax() - To find maximum element in the queue, we need to compare


with all the elements in the queue. This operation requires O(n) time
complexity.

remove() - To remove an element from the queue first we need to


perform findMax() which requires O(n) and removal of particular element
requires constant time O(1). This operation requires O(n) time complexity.

#2. Using an Unordered Array (Dynamic Array) with


the index of the maximum value
In this representation elements are inserted according to their arrival order
and maximum element is deleted first from max priority queue.

For example, assume that elements are inserted in the order of 8, 2, 3 and
5. And they are removed in the order 8, 5, 3 and 2.
Now, let us analyse each operation according to this representation...

isEmpty() - If 'front == -1' queue is Empty. This operation


requires O(1) time complexity that means constant time.

insert() - New element is added at the end of the queue with O(1) and for
each insertion we need to update maxIndex with O(1). This operation
requires O(1) time complexity that means constant time.

findMax() - To find maximum element in the queue is very simple as


maxIndex has maximum element index. This operation requires O(1) time
complexity.

remove() - To remove an element from the queue first we need to


perform findMax() which requires O(1) , removal of particular element
requires constant time O(1) and update maxIndex value which
requires O(n). This operation requires O(n) time complexity.
#3. Using an Array (Dynamic Array) in Decreasing
Order
In this representation elements are inserted according to their value in
decreasing order and maximum 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 analyse each operation according to this representation...

isEmpty() - If 'front == -1' queue is Empty. This operation


requires O(1) time complexity that means constant time.

insert() - New element is added at a particular position in the decreasing


order into the queue with O(n), because we need to shift existing elements
inorder to insert new element in decreasing order. This operation
requires O(n) time complexity.
findMax() - To find maximum element in the queue is very simple as
maximum element is at the beginning of the queue. This operation
requires O(1) time complexity.

remove() - To remove an element from the queue first we need to


perform findMax() which requires O(1), removal of particular element
requires constant time O(1) and rearrange remaining elements which
requires O(n). This operation requires O(n) time complexity.

#4. Using an Array (Dynamic Array) in Increasing


Order
In this representation elements are inserted according to their value in
increasing order and maximum element is deleted first from 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 8, 5, 3 and 2.
Now, let us analyse each operation according to this representation...

isEmpty() - If 'front == -1' queue is Empty. This operation


requires O(1) time complexity that means constant time.

insert() - New element is added at a particular position in the increasing


order into the queue with O(n), because we need to shift existing elements
inorder to insert new element in increasing order. This operation
requires O(n) time complexity.

findMax() - To find maximum element in the queue is very simple as


maximum element is at the end of the queue. This operation
requires O(1) time complexity.

remove() - To remove an element from the queue first we need to


perform findMax() which requires O(1), removal of particular element
requires constant time O(1) and rearrange remaining elements which
requires O(n). This operation requires O(n) time complexity.

#5. Using Linked List in Increasing Order


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 node with maximum value is deleted first from 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 8, 5, 3 and 2.
Now, let us analyse each operation according to this representation...

isEmpty() - If 'head == NULL' queue is Empty. This operation


requires O(1) time complexity that means constant time.

insert() - New element is added at a particular position in the increasing


order into the queue with O(n), because we need to the position where new
element has to be inserted. This operation requires O(n) time complexity.

findMax() - To find maximum element in the queue is very simple as


maximum element is at the end of the queue. This operation
requires O(1) time complexity.

remove() - To remove an element from the queue is simply removing the


last node in the queue which requires O(1). This operation
requires O(1) time complexity.

#6. Using Unordered Linked List with reference to


node with the maximum value
In this representation, we use a single linked list to represent max priority
queue. Always we maitain a reference (maxValue) to the node with
maximum value. In this representation elements are inserted according to
their arrival and node with maximum value is deleted first from max priority
queue.

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

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

isEmpty() - If 'head == NULL' queue is Empty. This operation


requires O(1) time complexity that means constant time.

insert() - New element is added at end the queue with O(1) and update
maxValue reference with O(1). This operation requires O(1)time
complexity.

findMax() - To find maximum element in the queue is very simple as


maxValue is referenced to the node with maximum value in the queue. This
operation requires O(1) time complexity.
remove() - To remove an element from the queue is deleting the node
which referenced by maxValue which requires O(1) and update maxValue
reference to new node with maximum value in the queue which
requires O(n) time complexity. This operation requires O(n)time
complexity.

2. Min Priority Queue Representations


Min Priority Queue is similar to max priority queue except removing
maximum element first, we remove minimum element first in 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.

Min priority queue is also has same representations as Max priority queue
with minimum value removal.

You might also like