0% found this document useful (0 votes)
6 views31 pages

DS_UNIT _3

The document provides a comprehensive overview of the Stack Data Structure, which operates on the LIFO (Last In First Out) principle. It covers the definition, types, basic operations (push, pop, top, isEmpty, isFull), and implementation methods using arrays and linked lists, along with their advantages and disadvantages. Additionally, it discusses the complexity analysis of stack operations and various applications of stacks in computing.

Uploaded by

manju.patnaik136
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)
6 views31 pages

DS_UNIT _3

The document provides a comprehensive overview of the Stack Data Structure, which operates on the LIFO (Last In First Out) principle. It covers the definition, types, basic operations (push, pop, top, isEmpty, isFull), and implementation methods using arrays and linked lists, along with their advantages and disadvantages. Additionally, it discusses the complexity analysis of stack operations and various applications of stacks in computing.

Uploaded by

manju.patnaik136
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/ 31

AITAM Data Structures MCA

UNIT – 3
STACKS
Definition:
Stack Data Structure is a linear data structure that follows LIFO (Last In First Out) Principle , so the last
element inserted is the first to be popped out. In this article, we will cover all the basics of Stack,
Operations on Stack, its implementation, advantages, disadvantages which will help you solve all the
problems based on Stack.

What is Stack Data Structure?

Stack is a linear data structure based on LIFO(Last In First Out) principle in which the insertion of a new
element and removal of an existing element takes place at the same end represented as the top of the
stack.

To implement the stack, it is required to maintain the pointer to the top of the stack , which is the last
element to be inserted because we can access the elements only on the top of the stack.

LIFO(Last In First Out) Principle in Stack Data Structure:

This strategy states that the element that is inserted last will come out first. You can take a pile of plates
kept on top of each other as a real-life example. The plate which we put last is on the top and since we
remove the plate that is at the top, we can say that the plate that was put last comes out first.

Representation of Stack Data Structure:

Stack follows LIFO (Last In First Out) Principle so the element which is pushed last is popped first.

Jayavardhanarao Sahukaru @ aitam 1


AITAM Data Structures MCA

Types of Stack Data Structure:


Fixed Size Stack : As the name suggests, a fixed size stack has a fixed size and cannot grow or shrink
dynamically. If the stack is full and an attempt is made to add an element to it, an overflow error occurs.
If the stack is empty and an attempt is made to remove an element from it, an underflow error occurs.

Dynamic Size Stack : A dynamic size stack can grow or shrink dynamically. When the stack is full, it
automatically increases its size to accommodate the new element, and when the stack is empty, it
decreases its size. This type of stack is implemented using a linked list, as it allows for easy resizing of
the stack.

Basic Operations on Stack Data Structure:

In order to make manipulations in a stack, there are certain operations provided to us.

• push() to insert an element into the stack


• pop() to remove an element from the stack
• top() Returns the top element of the stack.
• isEmpty() returns true if stack is empty else false.
• isFull() returns true if the stack is full else false.

Jayavardhanarao Sahukaru @ aitam 2


AITAM Data Structures MCA

Push Operation in Stack Data Structure:

Adds an item to the stack. If the stack is full, then it is said to be an Overflow condition.

Algorithm for Push Operation:

• Before pushing the element to the stack, we check if the stack is full .
• If the stack is full (top == capacity-1) , then Stack Overflows and we cannot insert the element to
the stack.
• Otherwise, we increment the value of top by 1 (top = top + 1) and the new value is inserted at top
position .
• The elements can be pushed into the stack till we reach the capacity of the stack.

Pop Operation in Stack Data Structure:

Removes an item from the stack. The items are popped in the reversed order in which they are pushed.
If the stack is empty, then it is said to be an Underflow condition.

Algorithm for Pop Operation:

• Before popping the element from the stack, we check if the stack is empty .
• If the stack is empty (top == -1), then Stack Underflows and we cannot remove any element from
the stack.
• Otherwise, we store the value at top, decrement the value of top by 1 (top = top – 1) and return
the stored top value.

Jayavardhanarao Sahukaru @ aitam 3


AITAM Data Structures MCA

Top or Peek Operation in Stack Data Structure:

Returns the top element of the stack.

Algorithm for Top Operation:

• Before returning the top element from the stack, we check if the stack is empty.
• If the stack is empty (top == -1), we simply print “Stack is empty”.
• Otherwise, we return the element stored at index = top .

isEmpty Operation in Stack Data Structure:

Returns true if the stack is empty, else false.

Algorithm for isEmpty Operation:

• Check for the value of top in stack.


• If (top == -1) , then the stack is empty so return true .
• Otherwise, the stack is not empty so return false .

Jayavardhanarao Sahukaru @ aitam 4


AITAM Data Structures MCA

isFull Operation in Stack Data Structure:

Returns true if the stack is full, else false.

Algorithm for isFull Operation:

• Check for the value of top in stack.


• If (top == capacity-1), then the stack is full so return true.
• Otherwise, the stack is not full so return false.

Jayavardhanarao Sahukaru @ aitam 5


AITAM Data Structures MCA

Implementation of Stack Data Structure:

The basic operations that can be performed on a stack include push, pop, and peek. There are two ways
to implement a stack –

• Using Array

• Using Linked List

In an array-based implementation, the push operation is implemented by incrementing the index of the
top element and storing the new element at that index. The pop operation is implemented by returning
the value stored at the top index and then decrementing the index of the top element.

In a linked list-based implementation, the push operation is implemented by creating a new node with
the new element and setting the next pointer of the current top node to the new node. The pop operation
is implemented by setting the next pointer of the current top node to the next node and returning the
value of the current top node.

Implementation of Stack Data Structure using Array:

// C program for array implementation of stack


#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

// A structure to represent a stack


struct Stack {
int top;
unsigned capacity;
int* array;
};
// function to create a stack of given capacity. It initializes size of
// stack as 0
struct Stack* createStack(unsigned capacity)
{
struct Stack* stack = (struct Stack*)malloc(sizeof(struct Stack));
stack->capacity = capacity;
stack->top = -1;
stack->array = (int*)malloc(stack->capacity * sizeof(int));
return stack;
}
// Stack is full when top is equal to the last index
int isFull(struct Stack* stack)
{
return stack->top == stack->capacity - 1;
}
// Stack is empty when top is equal to -1
int isEmpty(struct Stack* stack)
{
return stack->top == -1;

Jayavardhanarao Sahukaru @ aitam 6


AITAM Data Structures MCA

}
// Function to add an item to stack. It increases top by 1
void push(struct Stack* stack, int item)
{
if (isFull(stack))
return;
stack->array[++stack->top] = item;
printf("%d pushed to stack\n", item);
}
// Function to remove an item from stack. It decreases top by 1
int pop(struct Stack* stack)
{
if (isEmpty(stack))
return INT_MIN;
return stack->array[stack->top--];
}
// Function to return the top from stack without removing it
int peek(struct Stack* stack)
{
if (isEmpty(stack))
return INT_MIN;
return stack->array[stack->top];
}
// Driver program to test above functions
int main()
{
struct Stack* stack = createStack(100);
push(stack, 10);
push(stack, 20);
push(stack, 30);
printf("%d popped from stack\n", pop(stack));

return 0;
}

Output
10 pushed into stack
20 pushed into stack
30 pushed into stack
30 Popped from stack
Top element is : 20
Elements present in stack : 20 10

Advantages of Array Implementation:


• Easy to implement.
• Memory is saved as pointers are not involved.
Disadvantages of Array Implementation:

Jayavardhanarao Sahukaru @ aitam 7


AITAM Data Structures MCA

• It is not dynamic i.e., it doesn’t grow and shrink depending on needs at runtime. [But in case of
dynamic sized arrays like vector in C++, list in Python, ArrayList in Java, stacks can grow and
shrink with array implementation as well].
• The total size of the stack must be defined beforehand.

Implementation of Stack Data Structure using Linked List:

// C program for linked list implementation of stack


#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

// A structure to represent a stack


struct StackNode {
int data;
struct StackNode* next;
};

struct StackNode* newNode(int data)


{
struct StackNode* stackNode =
(struct StackNode*)
malloc(sizeof(struct StackNode));
stackNode->data = data;
stackNode->next = NULL;
return stackNode;
}

int isEmpty(struct StackNode* root)


{
return !root;
}

void push(struct StackNode** root, int data)


{
struct StackNode* stackNode = newNode(data);
stackNode->next = *root;
*root = stackNode;
printf("%d pushed to stack\n", data);
}

int pop(struct StackNode** root)


{
if (isEmpty(*root))
return INT_MIN;
struct StackNode* temp = *root;
*root = (*root)->next;
int popped = temp->data;
free(temp);

Jayavardhanarao Sahukaru @ aitam 8


AITAM Data Structures MCA

return popped;
}

int peek(struct StackNode* root)


{
if (isEmpty(root))
return INT_MIN;
return root->data;
}

int main()
{
struct StackNode* root = NULL;

push(&root, 10);
push(&root, 20);
push(&root, 30);

printf("%d popped from stack\n", pop(&root));


printf("Top element is %d\n", peek(root));
return 0;
}

Output
10 pushed to stack
20 pushed to stack
30 pushed to stack
30 popped from stack
Top element is 20
Elements present in stack : 20 10

Advantages of Linked List implementation:


• The linked list implementation of a stack can grow and shrink according to the needs at runtime.
• It is used in many virtual machines like JVM.
Disadvantages of Linked List implementation:
• Requires extra memory due to the involvement of pointers.
• Random accessing is not possible in stack.

Jayavardhanarao Sahukaru @ aitam 9


AITAM Data Structures MCA

Complexity Analysis of Operations on Stack Data Structure:

Advantages of Stack Data Structure:

• Simplicity: Stacks are a simple and easy-to-understand data structure, making them suitable
for a wide range of applications.
• Efficiency: Push and pop operations on a stack can be performed in constant time (O(1)) ,
providing efficient access to data.
• Last-in, First-out (LIFO): Stacks follow the LIFO principle, ensuring that the last element added
to the stack is the first one removed. This behavior is useful in many scenarios, such as function
calls and expression evaluation.
• Limited memory usage: Stacks only need to store the elements that have been pushed onto
them, making them memory-efficient compared to other data structures.

Disadvantages of Stack Data Structure:

• Limited access: Elements in a stack can only be accessed from the top, making it difficult to
retrieve or modify elements in the middle of the stack.
• Potential for overflow: If more elements are pushed onto a stack than it can hold, an overflow
error will occur, resulting in a loss of data.
• Not suitable for random access: Stack s do not allow for random access to elements, making
them unsuitable for applications where elements need to be accessed in a specific order.
• Limited capacity: Stacks have a fixed capacity, which can be a limitation if the number of
elements that need to be stored is unknown or highly variable.

Jayavardhanarao Sahukaru @ aitam 10


AITAM Data Structures MCA

Applications of Stack Data Structure:


• Infix to Postfix /Prefix conversion
• Redo-undo features at many places like editors, photoshop.
• Forward and backward features in web browsers
• In Memory management, any modern computer uses a stack as the primary management for a
running purpose. Each program that is running in a computer system has its own memory
allocations.
• Stack also helps in implementing function call in computers. The last called function is always
completed first.

Implementation of stack and its operations using arrays:

#include <stdio.h>
#include <stdlib.h>
#define MAX 4

int stack_arr[MAX];
int top = -1;

int isFull ()
{
if (top == MAX - 1)
return 1; //indicates the end of the function
else
return 0;
}
int isEmpty ()
{
if (top == -1)
return 1;
else
return 0;
}

void push (int data)


{
if(isFull())
{
printf("\nStack Overflow\n");
return;
}
top = top+1;
stack_arr[top] = data;
}

int pop ()
{
int value;
if(isEmpty ())

Jayavardhanarao Sahukaru @ aitam 11


AITAM Data Structures MCA

{
printf("\nStack underflow\n");
exit (1) ;
}
value = stack_arr[top];
top = top - 1;
return value;
}

int peek()
{
if(isEmpty ())
{
printf("Stack underflow\n");
exit (1);
}
return stack_arr[top];
}

void print ()
{
int i;
if (top == -1)
{
printf("Stack underflow\n");
return;
}
printf("\nThe elements in the stack are..");
for(i=top; i>=0; i -- )
printf("%d ", stack_arr[i]);
printf("\n");
}

int main ()
{
int choice, data;
while (1)
{
printf("\n");
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Print the top element\n");
printf("4. Print all the elements of the stack\n");
printf("5. Quit\n");
printf ("Please enter your choice: ") ;
scanf ("%d", &choice);

switch (choice)
{

Jayavardhanarao Sahukaru @ aitam 12


AITAM Data Structures MCA

case 1:
printf ("Enter the element to be pushed: ");
scanf ("%d", &data) ;
push (data);
break;

case 2:
data = pop () ;
printf ("\nDeleted element is %d\n", data);
break;

case 3:
printf ("\nThe topmost element of the stack is %d\n", peek() );
break;

case 4:
print ();
break;

case 5:
exit (1);

default:
printf("\nWrong choice\n");
}
}
return 0;
}

Jayavardhanarao Sahukaru @ aitam 13


AITAM Data Structures MCA

Implementation of stack and its operations using linked lists:

#include <stdio.h>
#include <stdlib.h>

struct node
{
int data;
struct node* link;
} *top = NULL;

int isEmpty()
{
if (top == NULL)
return 1;
else
return 0;
}

void push(int data)


{
struct node* newNode;
newNode = malloc(sizeof(newNode));
// Checking if memory can't be allocated for some reason
if (newNode == NULL)
{
printf("Stack Overflow.");
exit(1);
}
newNode->data = data;
newNode->link = NULL;

newNode->link = top;
top = newNode;
}

int pop()
{
struct node* temp;
int val;
if(isEmpty())
{
printf("Stack Underflow.");
exit(1);
}
temp = top;
val = temp->data;
top = top->link;
free (temp) ;

Jayavardhanarao Sahukaru @ aitam 14


AITAM Data Structures MCA

temp = NULL;
return val;
}

int peek()
{
if(isEmpty())
{
printf("Stack Underflow.");
exit(1);
}
return top->data;
}
void print()
{
struct node* temp;
temp = top;
if(isEmpty())
{
printf("Stack Underflow.");
exit(1);
}
printf("The stack elements are: ") ;
while(temp)
{
printf("%d ", temp->data);
temp = temp->link;
}
printf("\n");
}

int main()
{
int choice, data;
while(1)
{
printf("\n");
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Print the top element\n");
printf("4. Print all the elements of the stack\n");
printf("5. Quit\n");
printf ("Please enter your choice: ") ;
scanf ("%d", &choice) ;

switch(choice)
{
case 1:
printf("Enter the element to be pushed: ") ;

Jayavardhanarao Sahukaru @ aitam 15


AITAM Data Structures MCA

scanf("%d", &data);
push(data) ;
break;

case 2:
data = pop() ;
printf("Deleted element is %d\n", data);
break;

case 3:
printf("The topmost element of the stack is %d\n", peek() );
break;

case 4:
print();
break;

case 5:
exit(1) ;

default:
printf("Wrong choice\n");
}
}
return 0;
}

Jayavardhanarao Sahukaru @ aitam 16


AITAM Data Structures MCA

QUEUES
1. A queue can be defined as an ordered list which enables insert operations to be performed at one
end called REAR and delete operations to be performed at another end called FRONT.
2. Queue is referred to as First in First Out list.
3. For example, people waiting in line for a rail ticket form a queue.

Applications of Queue

Because queue performs actions on first in first out basis which is quite fair for the ordering of actions.
There are various applications of queues discussed as below.
1. Queues are widely used as waiting lists for a single shared resource like printer, disk, CPU.
2. Queues are used in asynchronous transfer of data (where data is not being transferred at the
same rate between two processes) for eg. pipes, file IO, sockets.
3. Queues are used as buffers in most of the applications like MP3 media player, CD player, etc.
4. Queues are used to maintain the play list in media players to add and remove the songs from
the play-list.
5. Queues are used in operating systems for handling interruptions.

Complexity

Types of Queues
What is a Queue?
Queue is the data structure that is like the queue in the real world. A queue is a data structure in which
whatever comes first will go out first, and it follows the FIFO (First-In-First-Out) policy. The queue can
also be defined as the list or collection in which the insertion is done from one end known as the rear
end or the tail of the queue, whereas the deletion is done from another end known as the front end or
the head of the queue.

Jayavardhanarao Sahukaru @ aitam 17


AITAM Data Structures MCA

The real-world example of a queue is the ticket queue outside a cinema hall, where the person who
enters first in the queue gets the ticket first, and the last person enters the queue gets the ticket at last.
A similar approach is followed in the queue in data structure.

The representation of the queue is shown in the image below –

Types of Queues

There are four different types of queues that are listed as follows -

o Simple Queue or Linear Queue


o Circular Queue
o Priority Queue
o Double Ended Queue (or Deque)

Simple Queue or Linear Queue

In Linear Queue, an insertion takes place from one end while the deletion occurs from another end. The
end at which the insertion takes place is known as the rear end, and the end at which the deletion takes
place is known as the front end. It strictly follows the FIFO rule.

The major drawback of using a linear Queue is that insertion is done only from the rear end. If the first
three elements are deleted from the Queue, we cannot insert more elements even though the space is

Jayavardhanarao Sahukaru @ aitam 18


AITAM Data Structures MCA

available in a Linear Queue. In this case, the linear Queue shows the overflow condition as the rear is
pointing to the last element of the Queue.

Circular Queue

In Circular Queue, all the nodes are represented as circular. It is similar to the linear Queue except that
the last element of the queue is connected to the first element. It is also known as Ring Buffer, as all
the ends are connected to another end. The representation of circular queue is shown in the image
below -

The drawback that occurs in a linear queue is overcome by using the circular queue. If the empty space
is available in a circular queue, the new element can be added in an empty space by simply
incrementing the value of rear. The main advantage of using the circular queue is better memory
utilization.

Priority Queue

It is a special type of queue in which the elements are arranged based on the priority. It is a special type
of queue data structure in which every element has a priority associated with it. Suppose some
elements occur with the same priority, they will be arranged according to the FIFO principle. The
representation of priority queue is shown in the below image -

Insertion in priority queue takes place based on the arrival, while deletion in the priority queue occurs
based on the priority. Priority queues are mainly used to implement the CPU scheduling algorithms.

There are two types of priority queue that are discussed as follows -
o Ascending priority queue - In ascending priority queue, elements can be inserted in arbitrary
order, but only smallest can be deleted first. Suppose an array with elements 7, 5, and 3 in the
same order, so, insertion can be done with the same sequence, but the order of deleting the
elements is 3, 5, 7.
o Descending priority queue - In descending priority queue, elements can be inserted in arbitrary
order, but only the largest element can be deleted first. Suppose an array with elements 7, 3,
and 5 in the same order, so, insertion can be done with the same sequence, but the order of
deleting the elements is 7, 5, 3.

Jayavardhanarao Sahukaru @ aitam 19


AITAM Data Structures MCA

Deque (or, Double Ended Queue)

In Deque or Double Ended Queue, insertion and deletion can be done from both ends of the queue
either from the front or rear. It means that we can insert and delete elements from both front and rear
ends of the queue. Deque can be used as a palindrome checker, which means that if we read the string
from both ends, then the string would be the same.
Deque can be used both as stack and queue as it allows the insertion and deletion operations on both
ends. Deque can be considered as stack because stack follows the LIFO (Last In First Out) principle in
which insertion and deletion both can be performed only from one end. And in Deque, it is possible to
perform both insertion and deletion from one end, and Deque does not follow the FIFO principle.
The representation of the deque is shown in the below image -

There are two types of deque that are discussed as follows -


o Input restricted deque - As the name implies, in input restricted queue, insertion operation can
be performed at only one end, while deletion can be performed from both ends.

o Output restricted deque - As the name implies, in output restricted queue, deletion operation
can be performed at only one end, while insertion can be performed from both ends.

Jayavardhanarao Sahukaru @ aitam 20


AITAM Data Structures MCA

Operations performed on queue

The fundamental operations that can be performed in a queue are listed as follows -
• Enqueue: The Enqueue operation is used to insert the element at the rear end of the queue. It
returns void.
• Dequeue: It performs the deletion from the front-end of the queue. It also returns the element
which has been removed from the front-end. It returns an integer value.
• Peek: This is the third operation that returns the element, which is pointed by the front pointer
in the queue but does not delete it.
• Queue overflow (isfull): It shows the overflow condition when the queue is completely full.
• Queue underflow (isempty): It shows the underflow condition when the Queue is empty, i.e.,
no elements are in the Queue.

Ways to implement the queue


There are two ways of implementing the Queue:
o Implementation using array: The sequential allocation in a Queue can be implemented using
an array.
o Implementation using Linked list: The linked list allocation in a Queue can be implemented
using a linked list.

Array implementation of Queue

We can easily represent queues by using linear arrays. There are two variables, i.e. front and rear, that
are implemented in the case of every queue. Front and rear variables point to the position from where
insertions and deletions are performed in a queue. Initially, the value of front and queue is -1 which
represents an empty queue. Array representation of a queue containing 5 elements along with the
respective values of front and rear, is shown in the following figure.

The above figure shows the queue of characters forming the English word "HELLO". Since, No deletion
is performed in the queue till now, therefore the value of front remains -1. However, the value of rear
increases by one every time an insertion is performed in the queue. After inserting an element into the
queue shown in the above figure, the queue will look like following. The value of rear will become 5 while
the value of front remains same.

Jayavardhanarao Sahukaru @ aitam 21


AITAM Data Structures MCA

After deleting an element, the value of front will increase from -1 to 0. however, the queue will look
something like following.

Algorithm to insert any element in a queue

Check if the queue is already full by comparing rear to max - 1. if so, then return an overflow error.
If the item is to be inserted as the first element in the list, in that case set the value of front and rear to
0 and insert the element at the rear end.
Otherwise keep increasing the value of rear and insert each element one by one having rear as the
index.
Algorithm
o Step 1: IF REAR = MAX - 1
Write OVERFLOW
Go to step
[END OF IF]
o Step 2: IF FRONT = -1 and REAR = -1
SET FRONT = REAR = 0
ELSE
SET REAR = REAR + 1
[END OF IF]
o Step 3: Set QUEUE[REAR] = NUM
o Step 4: EXIT

Function for enqueue

void enqueue(int value)


{
if (rear == MAX - 1)
{
printf("Queue is full!\n");
}
else
{
if (front == -1)
{
front = 0;
}
rear++;
queue[rear] = value;

Jayavardhanarao Sahukaru @ aitam 22


AITAM Data Structures MCA

printf("Inserted %d\n", value);


}
}

Algorithm to delete an element from the queue

If, the value of front is -1 or value of front is greater than rear , write an underflow message and exit.
Otherwise, keep increasing the value of front and return the item stored at the front end of the queue at
each time.
Algorithm
o Step 1: IF FRONT = -1 or FRONT > REAR
Write UNDERFLOW
ELSE
SET VAL = QUEUE[FRONT]
SET FRONT = FRONT + 1
[END OF IF]
o Step 2: EXIT

Function for dequeue

void dequeue()
{
if (front == -1 && rear == -1)
{
printf("Queue is empty!\n");
}
else if(front == rear)
{
front = rear = -1;
}
else
{
printf("Deleted %d\n", queue[front]);
front++;
}
}

Jayavardhanarao Sahukaru @ aitam 23


AITAM Data Structures MCA

Menu driven program to implement queue using array

#include <stdio.h>
#define MAX 3

int queue[MAX];
int front = -1;
int rear = -1;

void enqueue(int value)


{
if (rear == MAX - 1)
{
printf("Queue is full!\n");
}
else
{
if (front == -1)
{
front = 0;
}
rear++;
queue[rear] = value;
printf("Inserted %d\n", value);
}
}

void dequeue()
{
if (front == -1 && rear == -1)
{
printf("Queue is empty!\n");
}
else if(front == rear)
{
front = rear = -1;
}
else
{
printf("Deleted %d\n", queue[front]);
front++;
}
}

void display()
{
if (front == -1)
{
printf("Queue is empty!\n");

Jayavardhanarao Sahukaru @ aitam 24


AITAM Data Structures MCA

}
else
{
printf("Queue elements are: ");
for (int i = front; i <= rear; i++)
{
printf("%d ", queue[i]);
}
printf("\n");
}
}

void peek()
{
if (front == -1)
{
printf("Queue is empty!\n");
}
else
{
printf("The peek is %d\n", queue[front]);
}
}
int main()
{
int choice, value;
while (1)
{
printf("\nMenu:\n");
printf("1. Enqueue\n");
printf("2. Dequeue\n");
printf("3. Display\n");
printf("4. Peek\n");
printf("5. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
printf("Enter the value to be inserted: ");
scanf("%d", &value);
enqueue(value);
break;
case 2:
dequeue();
break;
case 3:
display();
break;

Jayavardhanarao Sahukaru @ aitam 25


AITAM Data Structures MCA

case 4:
peek();
break;
case 5:
return 0;
default:
printf("Invalid choice! Please try again.\n");
}
}
return 0;
}

Drawback of array implementation

Although, the technique of creating a queue is easy, but there are some drawbacks of using this
technique to implement a queue.
o Memory wastage : The space of the array, which is used to store queue elements, can never be
reused to store the elements of that queue because the elements can only be inserted at front
end and the value of front might be so high so that, all the space before that, can never be filled.

The above figure shows how the memory space is wasted in the array representation of queue. In the
above figure, a queue of size 10 having 3 elements, is shown. The value of the front variable is 5,
therefore, we can not reinsert the values in the place of already deleted element before the position of
front. That much space of the array is wasted and can not be used in the future (for this queue).
o Deciding the array size
On of the most common problem with array implementation is the size of the array which requires to
be declared in advance. Due to the fact that, the queue can be extended at runtime depending upon
the problem, the extension in the array size is a time taking process and almost impossible to be
performed at runtime since a lot of reallocations take place. Due to this reason, we can declare the
array large enough so that we can store queue elements as enough as possible but the main problem
with this declaration is that, most of the array slots (nearly half) can never be reused. It will again lead
to memory wastage.

Linked List implementation of Queue


Due to the drawbacks discussed in the previous section of this tutorial, the array implementation can
not be used for the large scale applications where the queues are implemented. One of the alternative
of array implementation is linked list implementation of queue.

Jayavardhanarao Sahukaru @ aitam 26


AITAM Data Structures MCA

The storage requirement of linked representation of a queue with n elements is o(n) while the time
requirement for operations is o(1).
In a linked queue, each node of the queue consists of two parts i.e. data part and the link part. Each
element of the queue points to its immediate next element in the memory.
In the linked queue, there are two pointers maintained in the memory i.e. front pointer and rear pointer.
The front pointer contains the address of the starting element of the queue while the rear pointer
contains the address of the last element of the queue.
Insertion and deletions are performed at rear and front end respectively. If front and rear both are NULL,
it indicates that the queue is empty.

The linked representation of queue is shown in the following figure.

Operation on Linked Queue

There are two basic operations which can be implemented on the linked queues. The operations are
Insertion and Deletion.
Insert operation
The insert operation append the queue by adding an element to the end of the queue. The new element
will be the last element of the queue.
Firstly, allocate the memory for the new node ptr by using the following statement.
1. Ptr = (struct node *) malloc (sizeof(struct node));
There can be the two scenario of inserting this new node ptr into the linked queue.
In the first scenario, we insert element into an empty queue. In this case, the condition front =
NULL becomes true. Now, the new element will be added as the only element of the queue and the
next pointer of front and rear pointer both, will point to NULL.
ptr -> data = item;
if(front == NULL)
{
front = ptr;
rear = ptr;
front -> next = NULL;
rear -> next = NULL;
}
In the second case, the queue contains more than one element. The condition front = NULL becomes
false. In this scenario, we need to update the end pointer rear so that the next pointer of rear will point
to the new node ptr. Since, this is a linked queue, hence we also need to make the rear pointer point to
the newly added node ptr. We also need to make the next pointer of rear point to NULL.
rear -> next = ptr;
rear = ptr;
rear->next = NULL;
In this way, the element is inserted into the queue. The algorithm and the C implementation is given as
follows.

Jayavardhanarao Sahukaru @ aitam 27


AITAM Data Structures MCA

Algorithm
o Step 1: Allocate the space for the new node PTR
o Step 2: SET PTR -> DATA = VAL
o Step 3: IF FRONT = NULL
SET FRONT = REAR = PTR
SET FRONT -> NEXT = REAR -> NEXT = NULL
ELSE
SET REAR -> NEXT = PTR
SET REAR = PTR
SET REAR -> NEXT = NULL
[END OF IF]
o Step 4: END

C function to insert an element in queue

void enqueue(int value)


{
struct Node* newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL)
{
printf("Memory allocation failed!\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if (rear == NULL)
{
front = rear = newNode;
}
else
{
rear->next = newNode;
rear = newNode;
}
printf("Inserted %d\n", value);
}

Deletion

Deletion operation removes the element that is first inserted among all the queue elements. Firstly, we
need to check either the list is empty or not. The condition front == NULL becomes true if the list is
empty, in this case , we simply write underflow on the console and make exit.
Otherwise, we will delete the element that is pointed by the pointer front. For this purpose, copy the
node pointed by the front pointer into the pointer ptr. Now, shift the front pointer, point to its next node
and free the node pointed by the node ptr. This is done by using the following statements.
ptr = front;
front = front -> next;

Jayavardhanarao Sahukaru @ aitam 28


AITAM Data Structures MCA

free(ptr);
The algorithm and C function is given as follows.

Algorithm
o Step 1: IF FRONT = NULL
Write " Underflow "
Go to Step 5
[END OF IF]
o Step 2: SET PTR = FRONT
o Step 3: SET FRONT = FRONT -> NEXT
o Step 4: FREE PTR
o Step 5: END

C function to delete an element in queue

void dequeue()
{
if (front == NULL)
{
printf("Queue is empty!\n");
return;
}
struct Node* temp = front;
front = front->next;
if (front == NULL)
{
rear = NULL;
}
printf("Deleted %d\n", temp->data);
free(temp);
}

Jayavardhanarao Sahukaru @ aitam 29


AITAM Data Structures MCA

Menu-Driven Program implementing all the operations on Linked Queue

#include <stdio.h>
#include <stdlib.h>

struct Node
{
int data;
struct Node* next;
};

struct Node* front = NULL;


struct Node* rear = NULL;

void enqueue(int value)


{
struct Node* newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL)
{
printf("Memory allocation failed!\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if (rear == NULL)
{
front = rear = newNode;
}
else
{
rear->next = newNode;
rear = newNode;
}
printf("Inserted %d\n", value);
}

void dequeue()
{
if (front == NULL)
{
printf("Queue is empty!\n");
return;
}
struct Node* temp = front;
front = front->next;
if (front == NULL)
{
rear = NULL;

Jayavardhanarao Sahukaru @ aitam 30


AITAM Data Structures MCA

}
printf("Deleted %d\n", temp->data);
free(temp);
}

void display()
{
if (front == NULL)
{
printf("Queue is empty!\n");
return;
}
struct Node* temp = front;
printf("Queue elements are: ");
while (temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}

void peek()
{
if (front == NULL)
{
printf("Queue is empty!\n");
return;
}
else
{
printf("Peek is %d\n", front->data);
}
}

int main()
{
enqueue(10);
enqueue(20);
enqueue(30);
peek();
display();
dequeue();
peek();
display();
return 0;
}

Jayavardhanarao Sahukaru @ aitam 31

You might also like