Unit - II: Linear Data Structure I
Unit - II: Linear Data Structure I
In the realm of computer science and programming, data structures are fundamental tools
that allow us to organize, manage, and store data efficiently. Among the various types of data
structures, linear data structures are the most basic and widely used. They are called "linear"
because they arrange data in a sequential manner, where elements are connected one after
another, like links in a chain or items in a list.
Linear data structures are essential for solving a wide range of computational problems. They
form the backbone of many algorithms and are often the first data structures introduced to
students learning programming. Their simplicity and versatility make them ideal for
understanding core concepts such as memory management, data access, and algorithmic
efficiency.
There are four primary types of linear data structures: Arrays, Stacks, Queues and Linked
Lists.
1. Arrays
An array is a collection of elements stored in contiguous memory locations. Each element
can be accessed directly using its index.
Advantages:
o Fast access using indices.
o Simple to implement.
Disadvantages:
o Fixed size (static memory allocation).
o Insertion and deletion are costly (require shifting elements).
Example:
Page 1 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
int arr[5] = {10, 20, 30, 40, 50};
Arrays are ideal for scenarios where the number of elements is known in advance and random
access is required.
2. Stacks
A stack is a linear data structure that follows the Last In, First Out (LIFO) principle. The last
element added is the first one to be removed.
Operations:
o Push: Add an element to the top.
o Pop: Remove the top element.
o Peek/Top: View the top element without removing it.
Applications:
o Function call management.
o Undo operations in editors.
o Expression evaluation (e.g., postfix notation).
Stacks are ideal for problems requiring backtracking or nested operations.
3. Queues
A queue is a linear data structure that follows the First In, First Out (FIFO) principle. The first
element added is the first one to be removed.
1. Operations:
o Enqueue: Add an element to the rear.
o Dequeue: Remove an element from the front.
o Front/Peek: View the front element.
2. Types:
o Simple Queue
o Circular Queue
o Priority Queue
o Deque (Double-Ended Queue)
3. Applications:
o Task scheduling.
o Print job management.
o Breadth-first search in graphs.
Queues are essential for managing tasks in order and handling asynchronous data.
4. Linked Lists
A linked list is a dynamic data structure where each element (called a node) contains data
and a reference (or pointer) to the next node.
Types:
o Singly Linked List: Each node points to the next node.
o Doubly Linked List: Each node points to both the next and previous nodes.
o Circular Linked List: The last node points back to the first node.
Advantages:
o Dynamic size.
o Efficient insertion and deletion.
Disadvantages:
Page 2 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
o Slower access (no direct indexing).
o Requires extra memory for pointers.
Linked lists are useful when the size of the data structure is unknown or frequently changes.
Linear data structures are the foundation of data organization in computer science. Their
simplicity, efficiency, and versatility make them indispensable tools for programmers and
software engineers. Understanding how they work, when to use them, and how to implement
them is crucial for solving complex problems and writing efficient code.
However, a strong grasp of linear data structures will serve as a solid base for mastering
these more complex structures.
Page 3 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.2. Topic: Introduction to Stacks
A stack is a linear data structure that follows the Last In, First Out (LIFO) principle, meaning
the last element added is the first to be removed. It operates through two main actions: push
(to add an element) and pop (to remove the top element).
Imagine a stack of plates in a cafeteria: you add plates to the top and remove them from the
top. This simple yet powerful concept is widely used in programming, algorithm design, and
system architecture.
Stacks are essential for managing data in a controlled and predictable manner. They are used
in various applications such as function call management, expression evaluation, syntax
parsing, and undo mechanisms in software. Understanding stacks is crucial for grasping more
advanced topics like recursion, compiler design, and memory management. They can be
implemented using arrays or linked lists. Due to their simple yet powerful structure, stacks
are fundamental in understanding recursion, memory management, and algorithm design.
The important variables used in the algorithms/ design of the Stacks are TOP & MAX_SIZE,
where TOP points to the topmost element in the stack and MAX_SIZE indicate the maximum
number of elements can be stored in the stack.
The other parameters used in the following algorithms is STACK, the storage space where the
elements of stack are stored.
The Value of TOP = -1, indicates that the stack is empty and if TOP = MAX_SIZE -1. Indicates
that the stack is full.
The various algorithms/operations of Stack are :
o Push: Add an element to the top.
o Pop: Remove the top element.
o Peek/Top: View the top element without removing it.
o IsEmpty : to check whether the stack is empty or not
o IsFull : to check whether the stack is Full or not
2.2.1. Algorithms:
1. Algorithm: Initialize Stack
Step 1: Define MAX_SIZE as the maximum capacity of the stack.
Step 2: Create an array STACK of size MAX_SIZE.
Step 3: Set TOP ← -1 to indicate the stack is initially empty.
2. Algorithm: PUSH(Element)
Input: Element to be added to the stack
Step 1: IF TOP == MAX_SIZE - 1, THEN
Display "STACK Overflow"
Go to Step 4.
Step 2: TOP ← TOP + 1.
Step 3:STACK[TOP] ← Element.
Step 4: End
Page 4 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
3. Algorithm: POP()
Output: Element removed from the stack
Step 1: If TOP == -1, THEN
Display "Stack Underflow" & Go To Step 5
Step 2: Element ← STACK[TOP]
Step 3: TOP ← TOP - 1
Step 4: Return Element
Step 5: End
4. Algorithm: PEEK()
Output: Element at the top of the stack
Step 1: If TOP == -1, then
Display "Stack is empty"
Exit
Step 2: Else
Return STACK[TOP].
Step 3: End
5. Algorithm: isEmpty()
Output: TRUE if stack is empty, FALSE otherwise
Step 1: If TOP == -1, then
Return TRUE.
Step 2: Else
Return FALSE.
Step 3: End
6. Algorithm: isFull()
Output: TRUE if stack is full, FALSE otherwise
Step 1: If TOP == MAX_SIZE - 1, then
Return TRUE.
Step 2: Else
Return FALSE.
Step 3: End
Page 5 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
4. Undo Mechanism
Applications like text editors use stacks to implement undo functionality. Each action is
pushed onto a stack, and undo pops the last action.
5. Backtracking Algorithms
Stacks are used in algorithms that require backtracking, such as maze solving, puzzle solving,
and depth-first search in graphs.
6. Browser History
Web browsers use stacks to manage the history of visited pages. The most recently visited
page is on top, and going back pops the current page.
Page 6 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.3. Topic: Introduction to Queues
Queues are classified in to four types
A queue is a fundamental linear data structure that operates on the principle of First In, First
Out (FIFO). This means that the first element added to the queue is the first one to be
removed. Think of a queue as a line of people waiting at a ticket counter—those who arrive
first are served first. This simple concept is widely used in computer science for managing
tasks, resources, and data flow in a sequential and orderly manner.
Among the various types of queues, the linear queue is the most basic. It arranges elements
in a straight line and allows insertion at one end (rear) and deletion from the other end
(front). Linear queues are used in numerous applications such as task scheduling, buffering,
and resource management.
Page 7 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
The important variables used in the algorithms/ design of the QUEUEs are FRONT, REAR &
MAX_SIZE, where FRONT points to the first element in the QUEUE, REAR points to the last
element in the queue,and MAX_SIZE indicate the maximum number of elements can be
stored in the Queue.
The other parameters used in the following algorithms is QUEUE, the storage space where
the elements of stack are stored.
The Value of FRONT = REAR = -1, indicates that the QUEUE is empty and if REAR = MAX_SIZE
-1, it indicates that the QUEUE is full.
2.3.1.3. Algorithms:
The various algorithms on Linear queue are :
2. Algorithm : Enqueue(Element)
Input: Element to be added to the Queue
Step 1: IF REAR = MAX_SIZE - 1, THEN
Display "QUEUE Overflow"
Go to Step 4.
Step 2: IF REAR = -1, THEN
FRONT ← REAR ← 0
ELSE
REAR ← REAR+1
Step 3: QUEUE[REAR] ← Element
Step 4: End
3. Algorithm : Dequeue()
Output: Element removed from the QUEUE
Step 1 : IF FRONT = -1, THEN
Display “QUEUE UNDERFLOW” & Go To Step 5.
Step 2 : Element ← QUEUE[FRONT].
Step 3 : IF FRONT = REAR, Then
Front ← REAR ← -1.
ELSE
Front ← FRONT + 1.
Step 4 : Return Element.
Step 5 : End.
Page 8 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
4. Algorithm : FRONT()
Output: Element returned from the front of the QUEUE
Step 1 : IF FRONT = -1, THEN
Display “QUEUE UNDERFLOW” & Go To Step 4.
Step 2 : Element ← QUEUE[FRONT].
Step 3 : Return Element.
Step 4 : End
5. Algorithm: isEmpty()
Output: TRUE if QUEUE is empty, FALSE otherwise
Step 1: If FRONT == -1, then
Return TRUE
Step 2: Else
Return FALSE
Step 3: End
6. Algorithm: isFull()
Output: TRUE if QUEUE is full, FALSE otherwise
Step 1: If REAR == MAX_SIZE - 1, then
Return TRUE
Step 2: Else
Return FALSE
Step 3: End
While linear queues are simple and easy to implement, they have some limitations, especially
in array-based implementations:
Wasted Space: After several dequeue operations, the front pointer moves forward,
leaving unused space at the beginning of the array.
Fixed Size: The maximum size is predetermined, which can lead to overflow even
when there is unused space.
No Reuse of Space: Once the rear reaches the end of the array, no more elements can
be added, even if there is space at the front.
These limitations are addressed by circular queues, which allow the rear to wrap around to
the beginning of the array.
1. Task Scheduling
Operating systems use queues to manage processes and tasks. Tasks are scheduled in
the order they arrive.
Page 9 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2. Print Queue
Printers use queues to manage print jobs. The first document sent to the printer is
printed first.
3. Customer Service Systems
Call centers and help desks use queues to manage customer requests. Requests are
handled in the order they are received.
4. Data Buffers
Queues are used in buffering data streams, such as audio or video playback, to ensure
smooth processing.
5. Breadth-First Search (BFS)
In graph traversal algorithms like BFS, queues are used to explore nodes level by level.
A circular queue is an advanced form of the linear queue that solves one of its major
limitations—wasted space due to the movement of the front and rear pointers. Like a linear
queue, a circular queue follows the First In, First Out (FIFO) principle, but with a twist: the
last position is connected back to the first position, forming a circle. This circular arrangement
allows efficient utilization of memory and is especially useful in systems where fixed-size
buffers are required.
Circular queues are widely used in real-time systems, operating systems, and embedded
systems where memory is limited and performance is critical. Understanding circular queues
is essential for mastering efficient data handling and resource management.
In a linear queue implemented using arrays, once the rear reaches the end of the array, no
more elements can be added—even if there is space at the front due to previous deletions.
This leads to inefficient memory usage.
A circular queue overcomes this by allowing the rear to wrap around to the beginning of the
array when space is available. This ensures that all positions in the array can be reused,
making it ideal for scenarios where memory is constrained.
Page 10 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.3.2.1. Characteristics of Circular Queue
2.3.2.3. Algorithms:
The various algorithms on Circular queue are similar to Linear Queue with difference in the
pointer updating:
1. Enqueue: Adds an element to the rear of the queue.
2. Dequeue: Removes an element from the front of the queue.
3. Front: Returns the front element without removing it.
4. isEmpty: Checks if the queue is empty.
5. isFull: Checks if the queue has reached its maximum capacity.
Page 11 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
3. Algorithm : Dequeue()
Output: Element removed from the QUEUE
Step 1 : IF FRONT = -1, THEN
Display “QUEUE UNDERFLOW” & Go To Step 5.
Step 2 : Element ← QUEUE[FRONT].
Step 3 : IF FRONT = REAR, Then
Front ← REAR ← -1.
ELSE IF FRONT = MAX_SIZE – 1, THEN
FRONT ← 0.
ELSE
Front ← FRONT + 1.
Step 4 : Return Element.
Step 5 : End.
4. Algorithm : FRONT()
Output: Element returned from the front of the QUEUE
Step 1 : IF FRONT = -1, THEN
Display “QUEUE UNDERFLOW” & Go To Step 4.
Step 2 : Element ← QUEUE[FRONT].
Step 3 : Return Element.
Step 4 : End
5. Algorithm: isEmpty()
Output: TRUE if QUEUE is empty, FALSE otherwise
Step 1: If FRONT == -1, THEN
Return TRUE
Step 2: Else
Return FALSE
Step 3: End
6. Algorithm: isFull()
Output: TRUE if QUEUE is full, FALSE otherwise
Step 1: IF (FRONT = 0 & REAR == MAX_SIZE – 1) OR (FRONT = REAR+1), THEN
Return TRUE
Step 2: Else
Return FALSE
Step 3: End
2.3.2.4. Advantages of Circular Queue
Efficient Memory Utilization: No wasted space due to shifting.
Fixed Size Control: Ideal for buffer management.
Fast Operations: Constant time insertion and deletion.
Predictable Behavior: Useful in real-time systems.
2.3.2.5. Disadvantages of Circular Queue
Complex Pointer Management: Requires careful handling of wrap-around logic.
Fixed Capacity: Cannot grow dynamically unless implemented with linked lists.
Overflow Risk: Must check for full condition before enqueue.
Page 12 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.3.2.6. Applications of Circular Queue
Circular queues are used in a variety of real-world and computational scenarios:
1. CPU Scheduling
Operating systems use circular queues to manage processes in round-robin
scheduling, where each process gets a fixed time slice.
2. Buffer Management
Circular queues are ideal for managing buffers in data streaming, audio/video
playback, and network packet handling.
3. Traffic Systems
Used in simulations of traffic lights and vehicle queues where cyclic behavior is
required.
4. Embedded Systems
Used in microcontrollers and real-time systems where memory is limited and
performance is critical.
5. Multitasking Systems
Circular queues help manage multiple tasks or threads in a cyclic order.
A priority queue is an advanced type of queue in which each element is associated with a
priority, and elements are served based on their priority rather than their order of arrival.
Unlike a regular queue that follows the First In, First Out (FIFO) principle, a priority queue
serves the element with the highest priority first, regardless of its position in the queue.
Priority queues are widely used in computer science and real-world applications where tasks
must be processed based on importance or urgency. Examples include CPU scheduling,
bandwidth management, emergency systems, and pathfinding algorithms like Dijkstra’s.
Page 13 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.3.3.2. Basic Operations of Priority Queue
Priority queues support the following operations:
1. Insert (Enqueue): Adds an element with a given priority.
2. Delete (Dequeue): Removes the element with the highest priority.
3. Peek: Returns the highest priority element without removing it.
4. isEmpty: Checks if the queue is empty.
5. Change Priority: Updates the priority of an existing element (optional in advanced
implementations).
Page 14 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
Operations in Heap-Based Priority Queue:
Insert: O(log n)
Delete Max/Min: O(log n)
Peek: O(1)
Priority queues are used to build Huffman trees for efficient data encoding.
A deque, short for double-ended queue, is a versatile linear data structure that allows
insertion and deletion of elements from both ends—front and rear. Unlike a regular
queue that follows the First In, First Out (FIFO) principle and restricts operations to
one end, a deque provides greater flexibility by supporting operations at both ends.
Deques are widely used in scenarios where elements need to be added or removed
Page 15 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
from either side efficiently. They are particularly useful in implementing algorithms
that require bidirectional access, such as sliding window problems, palindrome
checking, and task scheduling. Understanding deques is essential for mastering
advanced data structures and optimizing performance in real-time systems.
Types of Deque
There are two main types of deques:
1. Input-Restricted Deque
Insertion is allowed only at one end (usually rear).
Deletion is allowed from both ends.
2. Output-Restricted Deque
Deletion is allowed only at one end (usually front).
Insertion is allowed at both ends.
These variations allow deques to be tailored to specific application needs.
1. Bidirectional Access: Elements can be inserted or removed from both front and rear.
2. Linear Structure: Elements are arranged in a sequence.
3. Flexible Operations: Supports both stack-like (LIFO) and queue-like (FIFO) behavior.
4. Efficient Performance: Constant time insertion and deletion at both ends.
Page 16 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
8. isFull: Checks if the deque is full (in array-based implementation).
Page 17 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.4. Examples on the Application of Stacks & Queues
2.4.1. Stack Application Examples
Conversion of Infix Expression in to its equivalent Post-Fix Expression
Evaluation of Post- Fix Expression
Conversion of Infix Expression inn to its equivalent Pre-Fix (POLISH) Expression
Evaluation of Pre- Fix Expression
Balanced Parenthesis Checking Problem
Infix, prefix, and postfix expressions, commonly used in computer science and
mathematics:
1. Infix Expression
Definition: Operators are written between the operands.
Example: A + B
Usage: This is the most common notation used in arithmetic and algebra.
Challenge: Requires parentheses and operator precedence rules to avoid ambiguity.
2. Prefix Expression (Polish Notation)
Definition: Operators are written before the operands.
Example: + A B
Advantage: No need for parentheses; evaluation order is clear.
Usage: Used in some compilers and calculators.
Steps for Conversion of In-fix Expression in to its equivalent post fix expression, are as
follows:
1. Initialize
a. Create an empty stack for operators and PUSH ‘(‘ in to it add ‘)’ at the end of infix
expression.
b. Create an empty output list for the postfix expression.
2. Scan the Infix Expression from Left to Right
For each symbol in the expression:
a. IF Operand (e.g., A, B, 1, 2), THEN
1. Add directly to the output.
b. IF Left Parenthesis ‘(‘, THEN
1. Push onto the stack.
c. IF Right Parenthesis ‘)’, THEN
1. Pop from the stack and add to output until a left parenthesis ‘(‘ is
encountered.
2. Discard the left parenthesis.
Page 18 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
d. IF Operator (e.g., +, -, , /, ^), THEN
1. While the stack is not empty and the top of the stack has higher or equal
precedence,
pop from the stack and add to output.
2. Then push the current operator onto the stack.
3. After Scanning All Symbols, Pop all remaining operators from the stack and add to output.
4. End
Example 2. Convert the Infix: A + B/C- D*E - F in to its equivalent Postfix expressions.
Given: Infix Expression : A + B/C- D*E – F)
Symbol Stack Postfix Remarks
Scanned Expression
A ( A Put in to Expression(Step 2.a)
+ (+ A ‘+’ PUSH in to STACK(Step 2.d)
B (+ AB Put in to Expression(Step 2.a)
/ (+/ AB ‘/’ PUSH in to STACK(Step 2.d)
C (+/ ABC Put in to Expression(Step 2.a)
- (- ABC/+ Operator Precedence Resolved (Step 2.d)
D (- ABC/+D Put in to Expression(Step 2.a)
* (-* ABC/+D ‘*’ PUSH in to STACK(Step 2.d)
E (-* ABC/+DE Put in to Expression(Step 2.a)
- (- ABC/+DE*- Operator Precedence Resolved (Step 2.d)
F (- ABC/+DE*-F Put in to Expression(Step 2.a)
) EMPTY ABC/+DE*-F- POP all remaining operators from STACK(Step 2.c)
Equivalent Postfix Expression: ABC/+DE*-F-
Page 19 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.4.1.2. Evaluation of Post- Fix Expression with the help of Stack
Steps for Evaluation of Post-Fix Expression with the help of STACK are as follows:
1. Initialize an empty stack.
2. Scan the postfix expression from left to right.
3. For each symbol in the expression:
a. If operand (e.g., number or variable):
→ Push it onto the stack.
b. If operator (e.g., +, -, *, /):
→ Pop the top two elements from the stack.
→ Apply the operator: “second_operand” “operator” “first_operand”.
→ Push the result back onto the stack.
4. After the entire expression is scanned, the result will be the only element left in the stack.
Page 20 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
- 12 4 POP last two operands and PUSH their
evaluation result on STACK (Step 3.b)
* 48 POP last two operands and PUSH their
evaluation result on STACK (Step 3.b)
EMPTY POP the result
Answer is: 96
Page 21 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.4.1.4. Evaluation of Prefix Expression with the help of Stack
The steps for Evaluation of Pre-Fix Expression with the help of STACK are as follows:
1. Initialize an empty stack.
2. Scan the postfix expression from right to left.
3. For each symbol in the expression:
i. If operand (e.g., number or variable):
→ Push it onto the stack.
ii. If operator (e.g., +, -, *, /):
→ Pop the top two elements from the stack.
→ Apply the operator: “First_operand” “operator” “Second_operand”.
→ Push the result back onto the stack.
4. After the entire expression is scanned, the result will be the only element left in the
stack.
Page 22 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
Example 1. Check whether the given expression contains balanced parenthesis or not.
Expression: { [ ( ) ] }
Example 2. Check whether the given expression contains balanced parenthesis or not.
Expression: { [ ( {) ] }
The Josephus Problem is a famous theoretical puzzle in mathematics and computer science,
rooted in history and rich in algorithmic significance. The problem is named after Flavius
Josephus, a Jewish historian who lived during the 1st century AD. According to legend, during
the Jewish-Roman War, Josephus and his 40 soldiers were trapped in a cave by Roman forces.
Rather than surrender, they chose to commit suicide in a specific order. They formed a circle
and every third person was to be killed until only one remained. Josephus, not wanting to die,
figured out the position he should stand in to be the last survivor. This story gave rise to the
mathematical formulation of the problem. It involves a group of people standing in a circle,
where every k-th person is eliminated in a fixed sequence until only one person remains. The
challenge is to determine the position of the survivor. This problem is not only a fascinating
exercise in logic and recursion but also has practical applications in areas such as data
structures, game theory, and even cryptography.
It is defined as, Given: A group of people standing in a circle, numbered from 1 to n. starting
from a given position, every k-th person is eliminated from the circle, and the process
continues around the circle until only one person remains.
Goal: To determine the position of the last remaining person.
Page 23 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
Example:
If there are 7 (n = 7) people and every 3rd (k = 3) person is eliminated:
People: 1 2 3 4 5 6 7
Elimination order: 3 → 6 → 2 → 7 → 5 → 1 → 4 survives
4 is the winner in this problem.
Applications
1. Computer Science:
o Used in data structures like circular linked lists.
o Helps understand recursion and modular arithmetic.
o Useful in operating systems for scheduling algorithms.
2. Game Theory:
o Models elimination games and strategic positioning.
3. Cryptography:
o Concepts of safe positions and elimination can be applied in secure communication
protocols.
4. Simulation and Modelling:
o Used in simulations involving circular processes or turn-based systems.
Variants of the Problem
Several variations of the Josephus problem exist:
Changing step size: Instead of a fixed k, the step size changes dynamically.
Multiple survivors: Determine the last m survivors instead of just one.
Starting from different positions: The counting starts from a position other than
1.
Bidirectional elimination: Elimination alternates between clockwise and counter-
clockwise.
These variants add complexity and are often used in advanced algorithmic challenges.
Page 24 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.5. Recursion
A recursive function must have two essential parts: Base Case and Recursive Case.
Base Case: The condition under which the recursion stops. Without it, the function would
call itself indefinitely, leading to a stack overflow.
Recursive Case: The part where the function calls itself with a modified argument, moving
toward the base case.
factorial(n):
IF n = 0, THEN
return 1 # Base case
ELSE
return n * factorial(n - 1) # Recursive case
In recursive functions like factorial calculation, the stack plays a crucial role in managing
the flow of execution and memory. When a recursive function is called, the system uses a
call stack to keep track of each function invocation. Each time the function calls itself, a
new frame is pushed onto the stack, containing the function’s parameters, local variables,
and the return address. This continues until the base case is reached, which is the
condition that stops further recursion. For example, in calculating the factorial of a
number nn, the function Factorial(n) calls Factorial(n-1), which calls Factorial(n-2), and so
on, until it reaches Factorial(0), which returns 1. At this point, the stack begins to unwind.
The return value of Factorial(0) is passed back to Factorial(1), which multiplies it by 1 and
returns the result to Factorial(2), and this process continues until the original call
Factorial(n) receives the final result. Each step of this unwinding involves popping the top
frame off the stack and using its stored data to compute the result. This mechanism
ensures that each recursive call has its own isolated environment, preventing interference
between calls. However, because each call consumes stack memory, deep recursion can
Page 25 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
lead to stack overflow if the base case is not reached quickly or if the input is too large.
The stack also preserves the order of operations, ensuring that the last function called is
the first to return, which is essential for correctly computing values in recursive
algorithms. In the case of factorial, the multiplication happens during the unwinding
phase, meaning the actual computation is deferred until the base case is resolved. This
behavior highlights the importance of understanding stack dynamics when working with
recursion. The stack not only manages memory but also controls the logical flow of
recursive functions, making it a fundamental concept in programming. Without the stack,
recursion would not be possible, as there would be no way to remember where each
function left off or how to return to the previous state. Thus, the stack is the backbone of
recursive execution, enabling complex problems to be solved elegantly by breaking them
down into simpler sub-problems and systematically resolving them through a structured
and memory-managed process.
2. Example 2: Countdown
Function Countdown(n)
If n == 0, Then
Print "Blast off!"
Else
Print n
Countdown(n - 1)
End Function
2. Indirect Recursion: A function calls another function, which eventually calls the
original function.
Page 26 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
Function B(n)
If n > 0, Then
Print "B:", n
A(n // 2)
End Function
Function IsOdd(n)
If n == 0
Return False
Else
Return IsEven(n - 1)
End Function
3. Tail Recursion: The recursive call is the last operation in the function.
4. Head Recursion: The recursive call is made before any other operations.
Page 27 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2. Example 2: Head Recursive Sum
If n = 0, Then
Return 0
Else
result = HeadSum(n - 1)
Return result + n
End Function
Page 28 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
2.6. Exercise
Practice Questions:
1. What are linear data structures? Explain their key characteristics.
2. Define an array. What are its advantages and disadvantages?
3. What is a stack? Describe its basic operations.
4. Explain the LIFO principle with a real-life example.
5. What are the applications of stacks in computer science?
6. Describe the structure and types of linked lists.
7. What is a queue? How does it differ from a stack?
8. Explain the FIFO principle with a suitable analogy.
9. What are the types of queues? Briefly describe each.
10. What is a circular queue? How does it overcome the limitations of a linear queue?
11. Explain the concept and operations of a priority queue.
12. What is a deque? How is it different from a regular queue?
13. Write a short note on the applications of linear data structures in operating systems.
14. Compare arrays and linked lists in terms of access time and memory usage.
15. What is the role of the call stack in recursion?
16. Explain the algorithm for converting an infix expression to postfix using a stack.
17. How a postfix expression is evaluated using a stack?
18. What is the balanced parenthesis checking problem? How is it solved using stacks?
19. Describe the Josephus problem and its relevance to data structures.
20. What are the different types of recursion? Give examples of each.
Page 29 of 30
SVKMs NMIMS
Mukesh Patel School of Technology Management and Engineering, Shirpur
Course : Data Structures and Algorithms
--------------------------------------------------------------------------------------------------------
Postfix Expression Evaluation (Using Stack)
1. Stack it up: Evaluate the postfix expression “5 3 + 8 2 - *” using a stack. Show intermediate
stack states.
2. Arithmetic adventure: Given the postfix expression “6 2 / 3 4 * +”, compute the final result
using stack operations.
3. Operator overload: Evaluate “7 2 3 * - 4 +” using a stack. What is the final value?
4. Nested logic: Use a stack to evaluate the postfix expression “9 3 1 + / 2 *”.
5. Expression unraveling: Evaluate the postfix expression “4 5 + 6 2 / -” using stack-based steps.
Page 30 of 30