Unit 3 Notes
Unit 3 Notes
1 STACK
Stack is a linear data structure which follows the principle of Last In First Out(LIFO). In stack
insertion and deletion are done at only one end called top.
Basic operations:
• Push
• Pop
• Peek
• Isfull
• Isempty
Stack Implementation:
• Using Arrays
• Using Linked List
3.1.1 Stack using Arrays:
Creation
Here the stk is used to represent the stack and top is initialized to -1 at the beginning
#define size 10
int stack[size];
int top=-1;
Isfull operation:
Used to check whether stack is full or not. Returns 1 if stack is full and 0 otherwise.
int isfull()
if(top==size-1)
return 1;
return 0;
Isempty Operation
Used to check whether stack is empty or not. Returns 1 if stack is full and 0 otherwise. If top is -1,
there is no element into the stack.
int isempty()
if(top==-1)
return 1;
else
return 0;
}
Push Operation:
if(!isfull())
top=top+1;
stack[top]=val;
else
Pop Operation:
void pop()
if(!isempty())
top--;
else
Peek Operation
Displaying the element at the position top is called peek. It is done if the stack is not empty
void peek()
if(!isempty())
else
printf("\nStack is empty");
Display/Traverse
Display is done by iterating from top to bottom in stack. It is done if the stack is not empty
void display()
int i;
if(!isempty())
for(i=0;i<=top;i++)
printf("%d\t",stack[i]);
else
printf("\nStack is empty");
}
3.1.2 Stack using Linked List
Stack can be represented using Linked List where every node has data and a pointer to the next node.
Representation of Node
struct Node
int data;
};
Isempty Operation
Used to check whether stack is empty or not. Returns true if stack is full and false otherwise. If top is
NULL there is no element into the stack.
int isempty()
if(top==NULL)
return 1;
else
return 0;
Push Operation:
n1->data=val;
n1->next=top;
top=n1;
Pop Operation:
• Removing/Deleting an element at the top is called pop operation
• Pop operation is done if list is not empty.
• Stack Underflow: Trying to pop an element when stack is empty.
void pop()
{
struct stack *temp;
if(!isempty())
{
printf("\n The poped value is %d",top->data);
temp=top;
top=top->next;
free(temp);
}
else
printf("\nUnderflow:Stack is empty");
}
Peek Operation
Displaying the element at the position top is called peek. It is done if the stack is not empty
void peek()
{
if(!isempty())
{
printf("\n The value at top is %d",top->data);
}
else
printf("\nStack is empty");
}
Display Operation:
The stack is traversed by starting from top position to end of the list
void display()
{
struct stack *temp;
if(!isempty())
{
temp=top;
printf("\nThe elements of stacck are...");
while(temp!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
}
else
printf("\nEmpty stack");
}
3.1.3 Applications
Postfix notation is a notation for writing arithmetic expressions in which the operands appear before
their operators. There are no precedence rules to learn and parentheses are never needed.
• Operands are real numbers in single digits. (Read: Evaluation of PostfixExpressions for any
Number )
• Permitted operators: +,-, *, /, ^(exponentiation)
• Blanks are NOT permitted in expression.
• Parenthesis are permitted
Example:
Postfix: 54+
Output: 9
Explanation: Infix expression of above postfix is: 5+ 4 which resolves to 9
Postfix: 2536+**5/2-
Output: 16
Explanation: Infix expression of above postfix is: 2 * (5 *(3+6))/5-2 which resolves to 16
Algorithm:
Iterate through given expression, one character at a time
1. If the character is a digit, initialize number = 0
while the next character is digit
1. do number = number*10 + currentDigit
push number to the stack.
2. If the character is an operator,
pop operand from the stack, say it’s s1.
pop operand from the stack, say it’s s2.
perform (s2 operator s1) and push it to stack.
3. Once the expression iteration is completed, The stack will have the finalresult. pop from the stack
and return the result.
Tower of Hanoi
The tower of Hanoi is one of the main applications of recursion. It says, ‘if you can
solve n–1 cases, then you can easily solve the nth case
Look at Fig. 7.33 which shows three rings mounted on pole A. The problem is to move all these rings
from pole A to pole C while maintaining the same order. The main issue is that the smaller disk must
always come above the larger disk. We will be doing this using a spare pole. In our case, A is the source
pole, C is the destination pole, and B is the spare pole. To transfer all the three rings from A to C, we
will first shift the upper two rings (n–1 rings) from the source pole to the spare pole. We move the first
two rings from pole A to B as shown in Fig. 7.34. Now that n–1 rings have been removed from pole A,
the nth ring can be easily moved from the source pole (A) to the destination pole (C). Figure 7.35 shows
this step. The final step is to move the n–1 rings from the spare pole (B) to the destination pole (C).
This is shown in Fig. 7.36. To summarize, the solution to our problem of moving n rings from A to C
using B as spare can be given as:
Base case: if n=1
Recursive case:
3.2 QUEUE
Queue is a Linear data structures that follows the principle of First In First Out(FIFO)
Insertion is done at one end called rear and Deletion is done at another end called front.
Queue Implementation:
Queue can be implemented in two ways:
• Using Arrays
• Using Linked List
3.2.1 Queue Using Arrays
Creation
Here the queue is used to represent the queue, rear and front is initialized to -1 at the beginning when
the queue is empty.
#define size 10
int queue[size];
int front=-1;
int rear=-1;
Basic Operations
• Enqueue
• Dequeue
• Isfull
• Isempty
• Display
Isfull operation:
• Used to check whether queue is full or not. Returns true if queue is full and false otherwise.
int isfull()
{
if(rear==size-1)
return 1;
else
return 0;
}
Isempty Operation
• Used to check whether queue is empty or not. Returns true if queue is full and false otherwise.
If front is -1 there is no element into the queue.
int isempty()
{
if(front==-1 && rear==-1)
return 1;
else
return 0;
}
Enqueue Operation
• Inserting an element into queue is called enqueue.
• The queue is checked for full, Value is pushed into queue if it is not full.
• Enqueue operation is done by incrementing the rear value by 1.
• Overflow: Trying to insert an element when queue is full is called overflow.
void dequeue()
{
if(!isempty())
{
if(front==rear)
{
front=rear=-1;
}
else
{
front=front+1;
}
}
else
printf("\nUnderflow:Queue is empty");
}
Display/Traverse
Display is done by iterating from front to rear in queue. It is done if the queue is not empty.
void display()
{
int i;
if(!isempty())
{
printf("\nThe elements of queue are....");
for(i=front;i<=rear;i++)
{
printf("\n%d",queue[i]);
}
}
else
printf("\nQueue is empty");
}
Disadvantages:
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.
struct queue
{
int data;
struct queue *next;
}*front=NULL,*rear=NULL;
Basic Operations
• Enqueue
• Dequeue
• Isempty
• Display
Isempty Operation
Used to check whether queue is empty or not. Returns 1if queue is empty and 0 otherwise. If front is
NULL there is no element into the queue.
int isempty()
{
if(front==NULL && rear==NULL)
return 1;
else
return 0;
}
Enqueue Operation
void dequeue()
{
struct queue *temp;
if(!isempty())
{
printf("\nThe dequeued value is %d",front->data);
if(front==rear)
front=rear=NULL;
else
{
temp=front;
front=front->next;
free(temp);
}
}
}
Display/Traverse
Display is done by iterating from front to rear in queue. It is done if the queue is not empty.
void display()
{
struct queue *temp;
if(!isempty())
{
temp=front;
printf("\n The elements of queue are....");
while(temp!=NULL)
{
printf("\n%d",temp->data);
temp=temp->next;
}
}
else
printf("\nQueue is empty");
}
• Enqueue
• Dequeue
• Isfull
• Isempty
• Display
Representation of Circular Queue
#define size 5
int cqueue[size];
int front=-1;
int rear=-1;
Isfull operation:
Used to check whether queue is full or not. Returns 1 if queue is full and 0 otherwise.
int isfull()
{
if((rear+1)%size==front)
return 1;
else
return 0;
}
Isempty Operation
Used to check whether queue is empty or not. Returns 1 if queue is full and 0 otherwise. If front is -1
there is no element into the queue.
int isempty()
{
if(front==-1 && rear==-1)
return 1;
else
return 0;
}
Enqueue Operation
• Inserting an element into queue is called enqueue.
• The queue is checked for full, Value is pushed into queue if it is not full
• Enqueue operation is done by incrementing the rear value by 1 and modulo operator is used to
reach the beginning of queue to use deleted positions
• Overflow: Trying to insert an element when queue is full is called overflow.
Display is done by iterating from front to rear in queue. It is done if the queue is not empty.
void display()
{
int i;
if(!isempty())
{
printf("\nThe elements of queue are....");
for(i=front;i!=rear;i=(i+1)%size)
{
printf("\n%d",cqueue[i]);
}
printf("\n%d",cqueue[rear]);
}
else
printf("\nQueue is empty");
}
If there is no node,
create a newNode.
else (a node is already present)
insert the newNode at the end (last node from left to right.)
heapify the array
For Min Heap, the above algorithm is modified so that parentNode is always smaller than newNode.
Heap function
void heapify(int array[], int size, int i)
{
if (size == 1)
{
printf("Single element in the heap");
}
else
{
// Find the largest among root, left child and right child
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < size && array[l] > array[largest])
largest = l;
if (r < size && array[r] > array[largest])
largest = r;
Deletion operation
For Min Heap, the above algorithm is modified so that the both childNodes are smaller than
currentNode.
Swap Function
void swap(int *a, int *b)
{
int temp = *b;
*b = *a;
*a = temp;
}
Heap function
void heapify(int array[], int size, int i)
{
if (size == 1)
{
printf("Single element in the heap");
}
else
{
// Find the largest among root, left child and right child
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < size && array[l] > array[largest])
largest = l;
if (r < size && array[r] > array[largest])
largest = r;
// Swap and continue heapifying if root is not largest
if (largest != i)
{
swap(&array[i], &array[largest]); // swap() function call
heapify(array, size, largest);
}
}
}
Peek operation returns the maximum element from Max Heap or minimum element from Min Heap
without deleting the node.
Pseudo code
For both Max heap and Min Heap
return rootNode
3.5 DEQUE
The deque stands for Double Ended Queue. Deque is a linear data structure where the insertion and
deletion operations are performed from both ends. We can say that deque is a generalized version of
the queue.
Though the insertion and deletion in a deque can be performed on both ends, it does not follow the
FIFO rule. The representation of a deque is given as follows -
Types of deque
There are two types of deque -
• Input restricted queue
• Output restricted queue
In input restricted queue, insertion operation can be performed at only one end, while deletion can be
performed from both ends.
We can also perform peek operations in the deque along with the operations listed above. Through peek
operation, we can get the deque's front and rear elements of the deque. So, in addition to the above
operations, following operations are also supported in deque –
• Get the front item from the deque
• Get the rear item from the deque
• Check whether the deque is full or not
• Checks whether the deque is empty or not
Insertion at the front end
In this operation, the element is inserted from the front end of the queue. Before implementing the
operation, we first have to check whether the queue is full or not. If the queue is not full, then the
element can be inserted from the front end by using the below conditions –
o If the queue is empty, both rear and front are initialized with 0. Now, both will point to the first
element.
o Otherwise, check the position of the front if the front is less than 1 (front < 1), then reinitialize
it by front = n - 1, i.e., the last index of the array.
void insertfront(int val)
{
if(!isfull())
{
if(front==-1)
front=rear=0;
else
front=(front-1)%size;
queue[front]=val;
}
else
printf("Overflow:Queue is full");
}
Insertion at the rear end
In this operation, the element is inserted from the rear end of the queue. Before implementing the
operation, we first have to check again whether the queue is full or not. If the queue is not full, then the
element can be inserted from the rear end by using the below conditions -
o If the queue is empty, both rear and front are initialized with 0. Now, both will point to the first
element.
o Otherwise, increment the rear by 1. If the rear is at last index (or size - 1), then instead of
increasing it by 1, we have to make it equal to 0.
void insertrear(int val)
{
if(!isfull())
{
rear=(rear+1)%size;
queue[rear]=val;
if(front==-1)
front=rear;
}
else
printf("Overflow:Queue is full");
}
Deletion at the front end
In this operation, the element is deleted from the front end of the queue. Before implementing the
operation, we first have to check whether the queue is empty or not.
If the queue is empty, i.e., front = -1, it is the underflow condition, and we cannot perform the deletion.
If the queue is not full, then the element can be inserted from the front end by using the below conditions
-
If the deque has only one element, set rear = -1 and front = -1.
Else if front is at end (that means front = size - 1), set front = 0.
Else increment the front by 1, (i.e., front = front + 1).
void deletefront()
{
if(!isempty())
{
printf("\nThe dequeued value is %d",queue[front]);
if(front==rear)
{
front=rear=-1;
}
else
{
front=(front+1)%size;
}
}
else
printf("\nUnderflow:Queue is empty");
}
o Deque can be used as a palindrome checker means that if we read the string from both ends, the
string would be the same.
1.4 Applications of Queue
1. Task Scheduling
• Queues can be used to schedule tasks based on priority or the order in which they were received.
2. Resource Allocation
• Queues can be used to manage and allocate resources, such as printers or CPU processing time.
3. Batch Processing
• Queues can be used to handle batch processing jobs, such as data analysis or image rendering.
4. Message Buffering
• Queues can be used to buffer messages in communication systems, such as message
queues in messaging systems or buffers in computer networks.
5. Event Handling:
• Queues can be used to handle events in event-driven systems, such as GUI applications
or simulation systems.
6. Traffic Management:
• Queues can be used to manage traffic flow in transportation systems, such as airport
control systems or road networks.
7. Operating systems:
• Operating systems often use queues to manage processes and resources. For example,
a process scheduler might use a queue to manage the order in which processes are
executed.
8. Network protocols:
• Network protocols like TCP and UDP use queues to manage packets that are
transmitted over the network. Queues can help to ensure that packets are delivered in
the correct order and at the appropriate rate.
9. Printer queues :
• In printing systems, queues are used to manage the order in which print jobs are
processed. Jobs are added to the queue as they are submitted, and the printer processes
them in the order they were received.
10. Web servers:
• Web servers use queues to manage incoming requests from clients. Requests are added
to the queue as they are received, and they are processed by the server in the order
they were received.
11. Breadth-first search algorithm:
• The breadth-first search algorithm uses a queue to explore nodes in a graph level-by-
level. The algorithm starts at a given node, adds its neighbors to the queue, and then
processes each neighbor in turn.
Other Application of Queue in Data Structure
• Applied as buffers on playing music in the mp3 players or CD players.
• Applied on handling the interruption in the operating system.
• Applied to add a song at the end of the playlist.
• Applied as the waiting queue for using the single shared resources like CPU, Printers, or
Disk.
• Applied to the chat application when someone sends messages to us and we don’t have an
internet connection then the messages are stored in the server of the chat application