Dsa - Unit 2
Dsa - Unit 2
DATA
STRUCTURE
MI000000I
11000 00LLL
000 0000IO0 11 óc00001
1 10
Created By
10 0O0I0 111000I00111
1000 0000
000
Syllabus:
Stacks: Stack and its operations: Algorithms and their complexity analysis, Applications of Stacks:
Expression Conversion and evaluation -corresponding algorithms and complexity analysis.
Queue: Queue and Types of Queue: Simple Queue, Circular Queue, Priority Queue; Operations on
each type of Queue: Algorithms and their analysis.
Section 1: Stacks
1.1Stack Definition
A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle, where
the last element added is the first one to be removed. Stacks can be efficiently implemented
using arrays or linked lists.
Imagine a stack of plates. You add plates to the top of the stack and remove them from the
top. The last plate you put on the stack is the first one you take off.
Stack overflow error occurs when an attempt is made to push an element onto a full stack.
Stack underflow occurs when an attempt is made to pop an element from an empty stack.
Last
/ Function to initialize an empty stack
in
void initialize (struct Stack * first
D
->top =1; // Initialize top to -1 (empty stack) out
C
(LIFO)
B
/ Function to check if the stack is empty
int isEmpty (struc Stack *
STACK
return ->top ==
2
NotesNeo
returIE ->top MAX_SIZE 1:
push(&
push(&
push (&
10);
20);
30):
):1
EO
Top element : %d\n", peek(& )):
return 8:
NotesNeo
1.2 Stack Operations
1. Push: Adds an element to the top of the stack.
2. Pop: Removes the top element from the stack.
3. Peek/Top:Returns the top element without removing it. 3
4. isEmpty: Checks if the stack is empty.
1. Push:
Operation: The "push" operation is used to add an element onto the stack. When you push
an item onto the stack, it becomes the new top element.
Algorithm for Push Operation:
1) Check if the stack is full (in the case of a fixed-size stack).
2) If the stack is not full, increment the top pointer.
3) Place the new element at the top position in the stack.
4) If the stack is full, show the stack overflow error.
Complexity Analysis: The "push" operation takes constant time, O(1), as it involves a simple
increment of the top pointer, regardless of the stack's size.
2. Pop:
" Operation: The "pop" operation is used to remove the top element from the stack. When
you pop an item from the stack, it removes the top element and returns it.
Complexity Analysis: The "pop" operation takes constant time, O(1), as it involves a simple
decrement of the top pointer, regardless of the stack's size.
4
NotesNe0
3. Peek/Top:
Operation: The "peek" or "top" operation is used to view the top element without removing
it. It allows you to see the element currently at the top of the stack without modifying the
stack itself.
Algorithm: Return the element at the top of the stack without removing it.
Code (C Language): 4
int peek ()
if (top -1)
printf("'Stack is empty\n")A
return -1:
Complexity Analysis: The "peek" operation takes constant time, O(1), as it directly accesses
the top element.
4. IsEmpty:
Operation: The "isEmpty" operation is used to check if the stack is empty. It returns true if
the stack contains no elements and false otherwise.
Algorithm: Check if the top pointer is -1, indicating an empty stack.
Code (C Language):
int isEmpty() {
return top == -1
OTES
Complexity Analysis: The isEmpty operation has a constant time complexity of O(1). It
performsa single comparison to check the top pointer, regardless of the stack's size.
5. IsFull (for fixed-size stacks):
Operation: The "isFull" operation is used to check if the stack is full in the case of a
fixed-size stack. It returns true if the stack has reached its maximum capacity and false
otherwise.
Algorithm:Check if the top pointer is equal to the maximum allowed index, indicating that
the stack is full.
Code for IsFull Operation (C Language):
int isFull()
return top == MAX_SIZE - 1:
Complexity Analysis: The isFull operation also has a constant time complexity of O(1). It
performs a single comparison to check the top pointer, regardless of the stack's size.
5
NotesNeo
Recursion: Stacks are used to implement recursion in C. When a recursive function calls
itself, the parameters to the recursive call are pushed onto the stack. When the recursive
call returns, the parameters are popped off the stack.
Undo/redo: Stacks can be used to implement undolredo functionality in C. When an
operation is performed, the state of the program is pushed onto the stack. To undo the
operation, the state of the program is popped off the stack and restored.
Browsing history: Stacks can be used to implement browsing history in web browsers.
When a user visits a new web page, the URL of the page is pushed onto the stack. When
the user goes back or forward in their browsing history, the URLS are popped off the stack
and loaded.
Expression evaluation: Stacks are used to evaluate expressions in C. The operands of an 5
expression are pushed onto the stack, and the operators are applied to the operands in the
stack.
Reversing a string
Sorting a aray
2.1Expression Conversion
Infix notation is the standard mathematical notation we use every day, e.g.. 3 + 4. Postfix
(Reverse Polish Notation) and Prefix (Polish Notation) notations are alternative notations
for mathematical expressions. We'll discuss converting infix expressions to postfix and
prefix notations.
Polish notation is a mathematical notation in which every operator follows all of its
operands. This eliminates the need for parentheses and precedence to indicate the order of
operations.
In Polish notation, the order of operations is completely determined by the position of the
operators. There are two main forms of Polish notation:
1. Prefix Notation:
In prefix notation, the operator precedes its operands.
For example, the infix expression "3 + 4*5" would be written in prefix notation as "+
3*4 5".
2. Postfix Notation:
" In postfix notation, the operator follows its operands.
For example, the infix expression "3 + 4*5" would be written in postfix notation as
"3 45* +".
Expression conversion involves transforming mathematical expressions from one form to another,
such as converting from infix notation to postfix or prefix notation. Stacks play a crucial role in this
process.
Infix to Postfix Conversion:
o Algorithm:
1. Initialize an empty stack for operators.
2. Scan the infix expression from left to right.
3. If an operand is encountered, output it.
4. If an operator is encountered:
a. Pop operators from the stack and output them until an operator with
lower precedence is at the top or the stack is empty.
b. Push the current operator onto the stack.
6
NotesNe0
5. After scanning the expression, pop and output any remaining operators from
the stack.
Example:
Infix: a +b*c
Postfix: a bc* +
o Example:
Infix: (A+(B*C-(D/E-F)*G)*H)
Postfix: ABC*DE/F-G*-H*+
3 +
(+ A
4 ( (+( A
5. B (+( AB
6 (+(* AB
7 C (+(* ABC
8 (+( ABC*
9 (+(-( ABC*
ES
10. D (+(-( ABC*D
14. F
(+(-( ABC*DE/F
22. ABC*DE/F-G*-H*+
7
NotesNeo
return 0:
2. Dequeue:
" Operation: The "dequeue" operation is used to remove and return the front (first) element
from the queue. Dequeuing an item removes the front element and returns it.
Algorithm for Dequeue Operation:
1) Check if the queue is empty.
2) If the queue is not empty, return the element at the front.
3) Increment the front pointer.
12
NotesNeo
It can be efficiently implemented using arrays or linked lists.
Think of a queue in a real-world scenario like people waiting in line. The person who arrives
first is served first.
A B D F
QUEUE
Dequeue
Initialising a Queue(C Language):
define MAX SIZE 100 // Define maximum queue size
int queue[MAX_SIZE]: // Initialize an integer array for the queue
int front =-1; // Initialize the front pointer to -1
int rear = -1; 1/ Initialize the rear pointer to -1
(isEmpty(
10
NotesNeo
-front = ->rear = 0; // Initialize front and rear for the
first element
}else {
->rear = ->rear + 1) % MAX_SIZE; // Circular increment of
rear
OTES
return dequeuedValue;
Lnt
return
main () {
Struct
->arrl ->front ]:
EO
initialize(&
enqueue (&
enqueue(&
enqueue (&
11
NotesNeo
Complexity Analysis: The "dequeue" operation takes constant time, O(1), as it involves a
simple increment of the front pointer, regardless of the queue's size.
3. Front:
Operation: The "front" operation is used to view the front (first) element of the queue
without removing it. It allows you to see the element currently at the front of the queue
without altering the queue itself.
Algorithm for Front Operation:
Return the element at the front of the queue without modifying the queue itself.
Code for Front Operation (C Language):
int front() {
if (front > rear){
printf("Queue is empty\n"):
return-1:
Complexity Analysis: The "front" operation takes constant time, O(1), as it directly accesses
the front element.
4. IsEmpty:
" Operation: The "isEmpty" operation is used to check if the queue is empty. It returns true if
the queue contains no elements and false otherwise.
Algorithm:
Check if the front pointer is greater than the rear pointer, indicating an empty queue.
Code for IsEmpty Operation (C Language):
int isEmpty () 12
return front > rear:
Complexity Analysis: The "isEmpty" operation takes constant time, O(1), as it performs a
single comparison to check the front and rear pointers.
Complexity Analysis: The "isFull" operation takes constant time, O(1), as it performs a
single comparison to check the rear pointer, regardless of the queue's size.
13
NotesNeo
3.3 Types of Queues
1. Simple Queue: A simple queue is a basic queue where elements are inserted (enqueued)
at the rear and removed (dequeued) from the front in a First-In-First-Out (FIFO) order.
Example: Imagine people waiting in line at a ticket counter. The person who arrives
first gets the ticket first.
2. Circular Queue: A circular queue is similar to a simple queue but with a circular
arrangement of elements. It efficiently reuses space, and the rear and front pointers wrap
around.
Example: Think of a circular track where runners complete laps. When the last
runner reaches the end, they start from the beginning.
3. Priority Queue: A priority queue assigns priorities to elements and processes them based
on their priority levels, not necessarily in the order they were added. That means elements
are dequeued based on their priorities.
Example:in an hospital emergency room, patients are treated based on the severity
of their condition rather than the order of arrival. Critical patients are given higher
priority.
Operations:
1. Enqueue (Insertion):
" Algorithm:
OTES
Check if the queue is full.
If the queue is not full, increment the rear pointer.
Place the new element at the rear position in the queue.
C Code: 13
item)
(rear == MAX_SIZE -
printf("Queue Overflow\n"):
return:
queue[++rear] 1tem;
Time Complexity: O(1) - constant time, as it involves a simple increment of the rear
pointer, regardless of the queue's size.
2. Dequeue (Deletion):
Algorithm:
" Check if the queue is empty.
If the queue is not empty, return the element at the front.
Increment the front pointer.
C Code:
14
NotesNeo
Lnt deuUele() {
1f (front > rear) {
printf("Queue Underflow\n"):
return
Time Complexity: O(1) - constant time, as it involves a simple increment of the front
pointer, regardless of the queue's size.
3. Front (Peek):
Algorithm:
Return the element at the front of the queue without modifying the queue
itself.
C Code:
()
(front > rear)
printf("Queue is empty\n");
TetuN
return queue[front]:
Time Complexity: O(1) - constant time, as it directly accesses the front element.
4. IsEmpty:
Algorithm:
OIES
Check if the front pointer is greater than the rear pointer, indicating an empty
queue.
C Code:
Full Code:
14
#include <stdio . h>
queue[ MAX_SIZE]:
front =
rear =
( t item)
(rear == MAX_SIZE
15
NotesNeo
printf("Queue Overflow\n") :
return:
return queue[front]:
() {
OTES
return front > rear;
) {
1/ Sample usage of the simple queue
enqueue
enqueue ):
return
Operations:
16
NotesNe0
1. Enqueue (Insertion):
" Algorithm:
Check if the queue is full.
If the queue is not full, increment the rear pointer (considering circular
wrapping).
Place the new element at the rear position in the queue.
CCode:
item){
1f ((rear + ) % MAX_SIZE == front )
printf"Queue Overflow\n" )
return;
rear=(rear + ) % MAX_SIZE :
queue[rear] = item;
Time Complexity: O(1) - constant time, as it involves a simple increment of the rear
pointer with circular wrapping.
2. Dequeue (Deletion):
" Algorithm:
Check if the queue is empty.
If the queue is not empty, return the element at the front.
Increment the front pointer (considering circular wrapping).
OTES
CCode:
) {
1f (front ==
printf("Queue Underflow\n"):
return
dequeuedValue = queue[front ] :
1f (front == rear)
1/ Queue becomes empty after dequeueing the last
element
front= rear
}else
front = (front + ) % MAX_SIZE;
return dequeuedValue;
Time Complexity: O(1) - constant time, as it involves a simple increment of the front
16
pointer, regardless of the queue's size.
3. Front (Peek):
Algorithm:
Return the element at the front of the queue without modifying the queue
itself.
CCode:
17
NotesNe0
1f (front ==
printf("Queue is empty\n"):
Tetun
return queue[front ]:
Time Complexity: O(1) - constant time, as it directly accesses the front element.
4. IsEmpty:
Algorithm:
" Check if both the front and rear pointers are -1, indicating an empty circular
queue.
C Code:
5. IsFull:
Algorithm:
o Check if the next position of the rear pointer is equal to the front pointer,
indicating a full circular queue.
Ccode:
Full Code:
#nclude <stdio.h
EO
#define MAX_SIZE 100
queue[MAX_SIZE ]:
front =
rear =
1nt item)
1f ((rear + ) % MAX_SIZE = front) {
printf("Queue Overflow\n"):
retun: 17
(front ==
18
NotesNe0
printf("Is the queue empty? %s\n", isEmpty () ? "Yes" : "No") :
Time Complexity: O(n) in the worst case, as inserting an element with higher priority
might require shifting existing elements.
2. Dequeue (Deletion):
Algorithm:
Remove and return the element with the highest priority.
C Code:
uct Node
(front > rear) {
printf("Queue Unde rflow\n") :
20
19
NotesNeo
1/ If the queue is empty, set front to
front
(front ==
printf("Queue Underflow\n"):
return
dequeuedValue = queue[front ];
1f (front == rear)
1/ Queue becomes empty after dequeueing the last element
front rear=
} else{
front = (front + ) % MAX_SIZE;
return dequeuedValue ;
1f (front ==
printf("Queue is empty\n"):
TetuN
return queue[front]:
OTES
return front == && rear ==
19
(
18
NotesNeo
Struct Node emptyNode
return emptyNode;
queue [front++]:
Time Complexity: O(1) - constant time for removing the highest priority
element.
3. Front (Peek):
Algorithm:
Return the element at the front of the priority queue (highest priority) without
modifying the queue itself.
" C Code:
struct Node
1f (front > rear) {
printf("Queue is empty\n") ;
Struct Node emptyNode ={
ode o
return emptyNode;
return queue[front] :
Time Complexity: O(1) - constant time, as it directly accesses the highest priority
element.
4. IsEmpty:
Algorithm:
" Check if the priority queue is empty.
C Code:
){
return front > rear:
Time Complexity: O(1) - constant time for checking if the queue is empty.
Full Code:
#include <stdio.h>
struct Node {
value;
priority:
21
NotesNeo
struct Node queue[MAX_SIZE]:
front
rear =
rear++;
Lnt i = rear;
while (i > && item.priority > queue[i - ]-priority) {
queue[i] = queueli 11:
i--;
queue i = item;
struc Node
(front rear){
printf ("Queue Underflow\n"):
struct Node emptyNode 1}; // Return an empty node for
error
return emptyNode;
return queue[front] :
(){
front > rear;
enqueue (item1):
22
NotesNeo
enqueue(item2)
etUTT
Implementation May require more complex logic Simplified implementation due to the
Complexity for pointer management. circular structure.
Commonly used in scenarios Suitable for applications with cyclical
Use Cases where elements are processed in behavior, circular buffers, and tasks
the order they are added. repeating in cycles.
Enqueue and dequeue operations Enqueue and dequeue operations
Performance may require more pointer can be more efficient with
adjustments. constant-time pointer adjustments.
Memory May result in memory Less likely to result in memory
Management fragmentation over time. fragmentation.
Examples Supermarket checkout, printer Round-robin scheduling, circular
queue. buffer in communication systems.
23
NotesNeo
OTES
EO
24
24