0% found this document useful (0 votes)
77 views34 pages

Data Structure Lab Manual 2025-26

The document is a lab manual for the Data Structure course at ISBM College of Engineering, detailing various programming experiments using Python. It includes tasks such as managing library book borrowing records, implementing search algorithms, and creating undo/redo systems using stack and queue data structures. Each experiment outlines objectives, software/hardware requirements, theoretical concepts, and concludes with successful implementation results.

Uploaded by

SAMADHAN TAMBE
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)
77 views34 pages

Data Structure Lab Manual 2025-26

The document is a lab manual for the Data Structure course at ISBM College of Engineering, detailing various programming experiments using Python. It includes tasks such as managing library book borrowing records, implementing search algorithms, and creating undo/redo systems using stack and queue data structures. Each experiment outlines objectives, software/hardware requirements, theoretical concepts, and concludes with successful implementation results.

Uploaded by

SAMADHAN TAMBE
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

Peoples Empowerment Group

ISBM COLLEGE OF ENGINEERING, NANDE, PUNE

COMPUTER ENGINEERING DEPARTMENT

LAB MANUAL

Data Structure (PCC-204-COM)

LABORATORY

2025-26
INDEX

Sr. Title Page Date of Date of Signature


No No. Conduction Submission of Staff
Write a Python program to
manage the borrowing records of
books in a library. Implement the
following functionalities:
• Compute the average number
of books borrowed by all library
1
members.
• Find the book with the highest
and lowest number of borrowings
in the library.
• Count the number of members
who have not borrowed any
books (denoted by a borrow
count of 0).
• Display the most frequently
borrowed book (i.e., the mode of
borrow counts). After
performing, determine the time
and Space complexity of each
operation
In an e-commerce system,
customer account IDs are stored
in a list, and you are tasked with
writing a program that
implements the following:
2 • Linear Search: Check if a
particular customer account ID
exists in the list.
• Binary Search: Implement
Binary search to find if a
customer account ID exists,
improving the search efficiency
over the basic linear
Implementing a real-time
undo/redo system for a text
editing application using a Stack
data structure. The system
3
should support the following
operations:
• Make a Change: A new change
to the document is made.
• Undo Action: Revert the most
recent change and store it for
potential redo.
• Redo Action: Reapply the most
recently undone action.
• Display Document State: Show
the current state of the
document after undoing or
redoing an action
4 Implement a real-time event
processing system using a Queue
data structure. The system should
support the following features:
• Add an Event: When a new
event occurs, it should be added
to the event queue.
• Process the Next Event: The
system should process and
remove the event that has been in
the queue the longest.
• Display Pending Events: Show
all the events currently waiting to
be processed.
• Cancel an Event: An event can
be canceled if it has not been
processed.
5 Implement a hash table of size
10 and use the division method
as a hash function. In case of a
collision, use chaining.
Implement the following
operations:
• Insert(key): Insert key-value
pairs into the hash table.
• Search(key): Search for the
value associated with a given
key.
• Delete(key): Delete a key-
value pair from the hash table
6 Design and implement a hash
table of fixed size. Use the
division method for the hash
function and resolve collisions
using linear probing. Allow the
user to perform the following
operations:
• Insert a key
• Search for a key
• Delete a key
• Display the table
7 Implement various operations on
a Binary Search Tree, such as
insertion, deletion, display, and
search.
8 Construct an expression tree
from the given prefix expression,
e.g., +--a*bc/def, traverse it
using post-order traversal (non-
recursive), and then delete the
entire tree.
Group A
Experiment no. 1
Problem Statement:
Write a Python program to manage the borrowing records of books in a library. Implement the
following functionalities:
• Compute the average number of books borrowed by all library members.
• Find the book with the highest and lowest number of borrowings in the library.
• Count the number of members who have not borrowed any books (denoted by a borrow count
of 0).
• Display the most frequently borrowed book (i.e., the mode of borrow counts). After performing,
determine the time and Space complexity of each operation

Objectives:
1. To understand about concept of array in python
2. To know about various functions of list in python

Software and Hardware requirements:


Softwares:
 Operating System: 64-bit windows or Linux
 Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
 Dual-core /higher core processor(I3/I5)
 4/8GB RAM

Theory:
I. Concept of Array in Data Structure:
Array is a kind of data structure that can store a fixed-size sequential collection of
elements of the same type. An array is used to store a collection of data, but it is often more
useful to think of an array as a collection of variables of the same type. A specific element in
an array is accessed by an index. All arrays consist of contiguous memory locations. The lowest
address corresponds to the first element and the highest address to the last element.
You can define an array in python given below,
data = [ 1 . 6 , 3 . 4 , 5 . 5 , 9 . 4 ]
You can also use text like this:
Car_list = [ ”Volvo” , ” Tesla ” , ”Ford” ]
You can use Arrays in Loops like this:
for x in data :
print ( x )
You can return the number of elements in the array like this:
N = len( data )
You can get a specific value inside the array like this:
index = 22
x = cars[index]
You can use the append() method to add an element to an array:
[Link]( 11 . 4 )
Below are the list of various functions we can perform on array,
1. sort(): Sorts the list in ascending order.
2. type(list): It returns the class type of an object.
3. append(): Adds a single element to a list.
4. extend(): Adds multiple elements to a list.
5. index(): Returns the first appearance of the specified value.
6. max(list): It returns an item from the list with max value.
7. min(list): It returns an item from the list with min value.
8. len(list): It gives the total length of the list.
9. list(seq): Converts a tuple into a list.
10. cmp(list1, list2): It compares elements of both lists list1 and list2.
11. filter(fun,list): filter the list using the Python function.

II. Creation of array using array module in Python:


The array module in Python provides an efficient way to store and manipulate arrays of
basic numeric values. It is part of the Python Standard Library and offers a compact
representation for collections of homogeneous data, meaning all elements within
an array object must be of the same data type.

You can create array given below:


import array
A=[Link]("i",[2,3,4,18])
Here “i” is typecode means the data_type of elements
Values for Typecode are given below,
You can use below functions in array module,
 append(x): Adds a new item with value x to the end of the array.
 extend(iterable): Appends items from an iterable (like a list or another array) to the end of
the array.
 insert(i, x): Inserts a new item with value x before position i
 pop([i]): Removes and returns the item with index i. If i is not specified, it removes and
returns the last item.
 remove(x): Removes the first occurrence of value x from the array.
 count(x): Returns the number of occurrences of value x in the array.
 index(x): Returns the index of the first occurrence of value x in the array.
 reverse(): Reverses the order of the items in the array in place.
 tolist(): Converts the array to a plain Python list.
 fromlist(list): Appends items from a list to the array.
 frombytes(s): Appends items from a bytes object, interpreting the bytes as machine
values.
 tobytes(): Converts the array to a bytes object.

Algorithm: Write as per code by yourself

Flowchart: Write as per code by yourself

Conclusion:
In this way, we have successfully implemented Library-Book Borrowing system by using
python programming language.
Group A
Experiment no. 2
Problem Statement:
In an e-commerce system, customer account IDs are stored in a list, and you are tasked with
writing a program that implements the following:
 Linear Search: Check if a particular customer account ID exists in the list.
 Binary Search: Implement Binary search to find if a customer account ID exists,
improving the search efficiency over the basic linear

Objectives:
1. To understand the concept of Linear_search
2. To understand the concept of Binary_search

Software and Hardware requirements:


Softwares:
 Operating System: 64-bit windows or Linux
 Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
 Dual-core /higher core processor(I3/I5)
 4/8GB RAM

Theory:
I. Linear Search:
Linear search in Python is a simple searching algorithm used to find the presence and
location (index) of a specific element within a list or array.
It works by sequentially checking each element in the list until a match is found or
until the entire list has been examined.

 Time Complexity of Linear Search Algorithm:

1. Best Case:
The element being searched could be found in the first position. In this case, the
search ends with a single successful comparison. Thus, in the best-case scenario,
the linear search algorithm performs O(1) operations.

2. Worst Case:

The element being searched may be at the last position in the array or not at [Link]
the first case, the search succeeds in ‘n’ comparisons. In the next case, the search
fails after ‘n’ comparisons. Thus, in the worst-case scenario, the linear search
algorithm performs O(n) operations.

3. Average Case:
When the element to be searched is in the middle of the array, the average case of
the Linear Search Algorithm is O(n).

II. Binary Search:

Binary search looks for a particular key value by comparing the middle most item of the
collection. If a match occurs, then the index of item is returned. But if the middle item has a
value greater than the key value, the right sub-array of the middle item is searched. Otherwise,
the left sub-array is searched. This process continues recursively until the size of a subarray
reduces to zero.
Example:

 Time Complexity of Binary Search Algorithm:

1. Best Case:
The best case scenario of Binary Search occurs when the target
element is present at Mid. In this situation, there is only one
comparison. Therefore, the Best Case Time Complexity of Binary
Search is O(1).

2. Worst Case:
The worst-case scenario of Binary Search occurs when the target
element is the smallest element or the largest element of the
sorted array. Since the target element is present in the extremitites
(first or last index), there are logn comparisons in total. Therefore,
the Worst Case Time Complexity of Binary Search is O(logn).

3. Average Case:
The average case arises when the target element is present in some
location other than the central index or extremities. The time
complexity depends on the number of comparisons to reach the
desired element. The Average case time complexity is O(logn)

Algorithm: Write as per code by yourself


Flowchart: Write as per code by yourself

Conclusion:
In this way, we have successfully implemented Linear Search and Binary Search on E-
Commerce System.
Group B
Experiment no. 1
Problem Statement:
Implementing a real-time undo/redo system for a text editing application using a Stack data
Structure. The system should support the following operations:
● Make a Change: A new change to the document is made.
● Undo Action: Revert the most recent change and store it for potential redo.
● Redo Action: Reapply the most recently undone action.
● Display Document State: Show the current state of the document after undoing or
redoing an action

Objectives:
To understand how to use stack data structure for implementing undo and redo operations in real-
time applications like text editors.

Software and Hardware requirements:


Softwares:
● Operating System: 64-bit windows or Linux
● Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
● Dual-core /higher core processor(I3/I5)
● 4/8GB RAM

Theory:
I. Concept of Stack data Structure.

A Stack is a linear data structure that follows the LIFO (Last In, First Out) principle. This
means the element that is inserted last will be the first one to be removed. It is widely used in
programming for managing function calls, expression evaluation, and undo/redo operations

Key Operations on Stack:


1. Push(x): Insert an element x at the top of the stack.
2. Pop (): Remove and return the top element from the stack.
3. Peek/Top(): Return the top element without removing it.
4. isEmpty(): Check whether the stack is empty
Applications of Stack:
● Function calls management (recursion).
● Expression evaluation and conversion (infix, postfix, prefix).
● Undo/Redo functionality in text editors.
● Browser history navigation.
● Backtracking algorithms (e.g., maze solving, DFS).

Advantages of Stacks:
1. Simple to implement.
2. Provides efficient O(1) push and pop operations.
3. Useful for reversing data and managing history.

Disadvantages of Stack:
1. Limited size if implemented using arrays (fixed memory).
2. Access is restricted (can only access top element).

Thus, stack is an essential data structure in computer science and plays a key role in implementing
undo/redo operations.
In text editors, users frequently make changes to the document. To manage these changes, a real-
time Undo/Redo system is implemented using two stacks:

1. Make a Change: Each change is pushed onto the Undo stack


2. Undo Action: The most recent change is popped from the Undo stack and pushed onto the Redo
stack, reverting the document state.
3. Redo Action: The most recently undone action is popped from the Redo stack and pushed back
onto the Undo stack restoring the document state.
4. Display Document State: The current state of document state id display after each operation.

This approach ensures efficient management of text modifications in real-time applications like
notepad, word processors, and IDEs

Advantages
1. Provides flexibility in editing.
2. Improves user experience by restoring previous states.
3. Efficient with stack operations (O(1) per action).

Disadvantages:

1. Memory consumption may increase with very large history.


2. Limited by stack size if not managed properly.
Algorithm:

1. Initialize two stacks: UndoStack and RedoStack


2. On MakeChange(action): push action to UndoStack, clear RedoStack.
3. On Undo(): if UndoStack not empty, pop top action and push it to RedoStack
4. On Redo(): if RedoStack not empty, pop top action and push it back to UndoStack.
5. Display curent document state based on UndoStack.

Flowchart: Write as per code by yourself

Conclusion:
In this way, we have successfully implemented a real time Undo/Redo system for a text
editor using Stack data structure.
Group B
Experiment no. 2
Problem Statement:
Implement a real-time event processing system using a Queue data structure. The system should
support the following features:
 Add an Event: When a new event occurs, it should be added to the event queue.
 Process the Next Event: The system should process and remove the event that has been in the
queue the longest.
 Display Pending Events: Show all the events currently waiting to be processed.
 Cancel an Event: An event can be canceled if it has not been processed
Objectives:
To understand how to use Queue data structure for Implement a real-time event processing system.
Software and Hardware requirements:
Softwares:
 Operating System: 64-bit windows or Linux
 Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
 Dual-core /higher core processor(I3/I5)
 4/8GB RAM

Theory:
I. Concept of Queue data Structure.

A queue is a linear data structure where elements are stored in the FIFO (First In First Out)
principle where the first element inserted would be the first element to be accessed. A queue is
an Abstract Data Type (ADT) similar to stack; the thing that makes queue different from stack is
that a queue is open at both its ends. The data is inserted into the queue through one end and
deleted from it using the other end. Queue is very frequently used in most programming
languages. A queue has two main ends:

A real-world example of queue can be a single-lane one-way road, where the vehicle enters first,
exits first. More real-world examples can be seen as queues at the ticket windows and bus-stops.
Queue operations work as follows:

 Two pointers are there denoting two ends, FRONT and REAR.
 FRONT Tracks the first element of the queue.
 REAR Tracks the last element of the queue.
 Initially, set the value of FRONT and REAR to -1.
 Afterward, follow the above-given algorithms for the basic operations.

Key Operations on Queue:


1. Enqueue – Adds an element to the rear of the queue.
2. Dequeue – Removes and returns the front element.
3. Peek/Front – Returns the front element without removing it.
4. isEmpty – Checks if the queue is empty.
5. isFull – Checks if the queue is full (for fixed-size queues).

Real-Time Event Processing System using Queue

In a real-time environment, events (like user actions, sensor signals, or messages) occur
dynamically and need to handled in the order they arrive.
A Queue data structure is ideal for this because it ensures fair, ordered, and efficient processing.

Working:

Add an Event (Enqueue):


When a new event occurs (e.g., mouse click, network request, or interrupt), it is added to the rear
of the queue.

Process the Next Event (Dequeue):


The system processes the event at the front of the queue, i.e., the event that has been waiting the
longest.

Display Pending Events:


At any point, the system can show all events currently waiting in the queue.
Display Pending Events:
At any point, the system can show all events currently waiting in the queue.

Cancel an Event:
If an event is no longer needed before processing (e.g., a cancelled request), it can be removed
from the queue.

Example in Real Life

1. In an operating system, processes waiting for CPU time are kept in a ready queue.

2. In a printer spooler, print jobs are queued and executed in the order they were submitted.

3. In a real-time event manager, user actions (keyboard input, mouse clicks) are stored in a queue
and processed sequentially.
Algorithm:
1) Insertion: enqueue()
Algorithm
Step 1: START
Step 2: Check if the queue is full.
Step 3: If the queue is full, produce an overflow error and exit.
Step 4: If the queue is not full, increment the rear pointer to point to the next space.
Step 5: Add a data element to the queue location, where the rear is pointing.
Step 6: End the process and exit.
2) Deletion: dequeue()
Algorithm
Step 1: START
Step 2: Check if the queue is empty.
Step 3: If the queue is empty, print underflow and exit.
Step 4: If the queue is not empty, access the data where the front is pointing.
Step 5: Increment the front pointer to point to the next available data element.
Step 6: Set the front and rear as -1 for the last element.
Step 7: End the process and exit.

3) Peek ()
Algorithm
Step 1: START
Step 2: Check if the Queue is empty.
Step 3: Return the element at the front of the queue
Step 4: End the process and exit.

4) isFull()
Algorithm
Step 1: START
Step 2: If the count of queue elements equals the queue size, return true.
Step 3: Otherwise, return false
Step 4: End the process and exit.

5) isEmpty()
Algorithm
Step 1: START
Step 2: If the count of queue elements equals zero, return true.
Step 3: Otherwise, return false
Step 4: End the process and exit.

Flowchart: Write as per code by yourself

Conclusion:
In this way, we have successfully implemented a real-time event processing system Using
Queue data structure.
Group C
Experiment no. 1
Problem Statement:
Implement a hash table of size 10 and use the division method as a hash function. In case of a collision,
use chaining. Implement the following operations:

• Insert(key): Insert key-value pairs into the hash table.


• Search(key): Search for the value associated with a given key.
• Delete(key): Delete a key-value pair from the hash table

Objectives:
To understand how to implement a hash table of size 10 and use the division method as a hash function.
In case of a collision, use chaining.
Software and Hardware requirements:
Softwares:
 Operating System: 64-bit windows or Linux
 Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
 Dual-core /higher core processor(I3/I5)
 4/8GB RAM

Theory:
I. Concept of Hash Table

In hashing there is a hash function that maps keys to some values. But these hashing functions may lead
to a collision that is two or more keys are mapped to same value. Chain hashing avoids collision. The
idea is to make each cell of hash table point to a linked list of records that have same hash function
value.
Collision:
Collision is the situation when the bucket index is not empty. It means that a linked list head is present
at that bucket index. We have two or more values that map to the same bucket index.

For a more detailed explanation and theoretical background on this approach, please refer to Hashing |
Set 2 (Separate Chaining).

Let's create a hash function, such that our hash table has 'n' number of buckets.

To insert a node into the hash table, we first compute the hash index for the given key using a hash
function:
Hash Index = key % no Of Buckets.
This index determines the appropriate bucket where the node should be inserted.
Example:
No Of Buckets = 7
Keys to insert = [15, 11, 27, 8]

For each key:

15 % 7 = 1
11 % 7 = 4
27 % 7 = 6
8%7=1
Insert: Move to the bucket corresponding to the above-calculated hash index and insert the new node
at the end of the list.
Delete: To delete a node from hash table, calculate the hash index for the key, move to the bucket
corresponding to the calculated hash index, and search the list in the current bucket to find and remove
the node with the given key (if found).

Key Operations on Queue:


 Insertion
 Search
 Hash Function
 Delete

 Insertion: Inserts the key-value pair at the head of a linked list which is present at the given
bucket index.
 hashfunction: Gives the bucket index for the given key. Our hash function = ASCII value
of character * primeNumberx. The prime number in our case is 31 and the value of x is
increasing from 1 to n for consecutive characters in a key.
 Deletion: Deletes key-value pair from the hash table for the given key. It deletes the node
from the linked list which holds the key-value pair.

 Search: Search for the value of the given key.


This implementation does not use the rehashing concept. It is a fixed-sized array of linked
lists.

Time Complexity and Space Complexity:

The time complexity of hash table insertion and deletion operations is O(1) on average. There is
some mathematical calculation that proves it.

 Time Complexity of Insertion: In the average case it is constant. In the worst case, it is
linear.
 Time Complexity of Search: In the average case it is constant. In the worst case, it is
linear.
 Time Complexity of Deletion: In average cases it is constant. In the worst case, it is linear.
 Space Complexity: O(n) as it has n number of elements.

Algorithm: Write as per code by yourself

Flowchart: Write as per code by yourself

Conclusion:
In this way, we have successfully implemented a hash table of size 10 and use the division method as
a hash function. In case of a collision, use chaining.
Group C
Experiment no. 2
Problem Statement:
Design and implement a hash table of fixed size. Use the division method for the hash function and resolve
collisions using linear probing. Allow the user to perform the following operations:

• Insert a key
• Search for a key
• Delete a key
• Display the table

Objectives:
To understand how to implement a hash table of fixed size. Use the division method for the hash function
and resolve collisions using linear probing
Software and Hardware requirements:
Softwares:
 Operating System: 64-bit windows or Linux
 Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
 Dual-core /higher core processor(I3/I5)
 4/8GB RAM

Theory:
I. Concept of hash table of fixed size

Hash Table

A hash table is a data structure that stores key-value pairs. It uses a hash function to compute
an index (also called a hash code) into an array of buckets or slots, from which the desired value
can be found.

Hash tables provide efficient:

 Insertion
 Search
 Deletion

Typically, these operations have a time complexity of O(1) on average.


Hash Function (Division Method)

A hash function determines the index at which a key should be stored in the hash table. The
division method is a simple and commonly used hashing technique where the hash value is
computed as:

hash(key)=keymodtable_size

This ensures that the resulting index is within the bounds of the array.

Fixed-Size Table

A fixed-size hash table has a pre-defined number of slots. It does not dynamically resize as
elements are added, so proper collision handling is essential to maintain performance and
correctness.

Collisions

A collision occurs when two keys are hashed to the same index. Since we cannot store multiple
keys in the same slot (in this implementation), we need a collision resolution technique.

Linear Probing

Linear probing is a collision resolution method where, if a collision occurs, we probe the next
slot (i.e., move sequentially) until an empty slot is found.

Example:

 Suppose key 17 and key 24 both hash to index 3.


 If slot 3 is occupied, we check 4, then 5, and so on, until we find an empty slot.

This method is simple and easy to implement but may suffer from primary clustering (grouping
of entries).

Deletion Handling

To delete a key in linear probing, we cannot simply set the slot to None, because this would break
the probing chain. Instead, we use a special marker (e.g., "<deleted>") to indicate a deleted slot,
allowing search and insertion to continue correctly.
Operations Supported

 Insert(key): Adds a key to the hash table using linear probing in case of collision.
 Search(key): Locates the key in the table using the same probing logic.
 Delete(key): Marks the key as deleted using a special marker.
 Display(): Shows the current state of the hash table.

Applications:

 Symbol tables in compilers


 Caches and lookup tables
 Databases and memory management systems

Algorithm: Write as per code by yourself

Flowchart: Write as per code by yourself

Conclusion:
In this way, we have successfully implement a hash table of fixed size. Use the division method for the
hash function and resolve collisions using linear probing.
Group D
Experiment no. 3
Problem Statement:
Implement various operations on a Binary Search Tree, such as insertion, deletion, display,
and search.
Objectives:
1. To understand the concept of binary search tree as a data structure.
2. Applications of BST.

Software and Hardware requirements:


Softwares:
 Operating System: 64-bit windows or Linux
 Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
 Dual-core /higher core processor(I3/I5)
 4/8GB RAM

Theory:
I. Definition of binary search tree in Data Structure:
A binary tree in which each internal node x stores an element such that the element stored in
the left subtree of x are less than or equal to x and elements stored in the right subtree of x are
greater than or equal to x. This is called binary-search-tree property.
This property enables efficient search, insertion, and deletion operations in a BST.

II. Insertion Operation

The insertion operation in a BST involves adding a new element to the tree while
maintaining the binary search tree property. The steps for inserting a new element into a
BST are as follows:
1. Start at the root node of the tree.
2. If the tree is empty, create a new node and set it as the root.
3. If the value of the new element is less than the value of the current node, move to the left
child.
4. If the left child is empty, create a new node with the new element and set it as the left child
of the current node.
5. If the left child is not empty, repeat steps 3–5 recursively on the left subtree.
6. If the value of the new element is greater than the value of the current node, move to the
right child.
7. If the right child is empty, create a new node with the new element and set it as the right
child of the current node.
8. If the right child is not empty, repeat steps 6–8 recursively on the right subtree.
9. Once the new element is inserted, the binary search tree property is maintained.
The insertion operation has a time complexity of O(log n) on average in a balanced BST,
where n is the number of elements in the tree. However, in the worst case scenario where
the tree is highly unbalanced, the time complexity can degrade to O(n).

III. Search Operation

The search operation in a BST involves finding a specific element within the tree. The steps
for searching an element in a BST are as follows:
1. Start at the root node of the tree.
2. If the tree is empty or the current node’s value matches the target value, return the current
node.
3. If the target value is less than the value of the current node, move to the left child.
4. If the target value is greater than the value of the current node, move to the right child.
5. Repeat steps 2–4 until the target value is found or a leaf node is reached.
6. If the target value is not found after reaching a leaf node, it does not exist in the tree.
The search operation in a BST has a time complexity of O(log n) on average in a balanced
BST. In the worst case scenario, where the tree is highly unbalanced (essentially a linked
list), the time complexity becomes O(n).

IV. Deletion Operation


Deleting a node in Binary search tree involves deleting an existing node while maintaining the
properties of Binary Search Tree(BST). we need to search the node which needs to be deleted
and then delete it.
Case 1 : While deleting a node having both left child and right child
 After finding the node to be deleted, copy the value of right child to v and copy the right
child's left pointer to left of v and right pointer

Delete node 18 in BST

 In the above example, suppose we need to delete 18 then we need to replace 18 with the
maximum value of its left or right sub tree
 Let us replace it with 20 which is maximum value of right sub tree
 So after deleting 18, the Binary search tree looks like this

Case 2 : While deleting a node having either left child or right child
 After finding the node to be deleted, we need to replace the value in the node with its left
node it has left child or right node if it has right child.
Delete 16 in BST

 In the above example, suppose we need to delete 16 then we need to replace 16 with the
value of its right child node
 So it will be replaced with 17 which is the value of its right child node
 So after deleting 16, the Binary search tree looks like this

Deleted 16 in BST

Case 3 : While deleting a leaf node(a node which has no child)

Delete 4 in BST
 In the above example, suppose we need to delete 4 which is a leaf node.
 Simply we change value of the node, left and right pointers to None.
 After deleting 4 the BST looks like this:

Deleted 4 in BST
V. Display Operation
The display operation is used to visually represent or print the data elements stored in the BST.
Since the BST structure is hierarchical, the display is usually done using tree traversals —
recursive techniques that visit all nodes in a specific order.

1 To show the elements present in the BST.

2 To verify the tree structure after insertion or deletion.

3 To help understand how the BST property (Left < Root < Right) is maintained.

4 To allow visualization of sorted order of elements using Inorder Traversal.

Algorithm: Write as per code by yourself

Flowchart: Write as per code by yourself

Conclusion:
We have learned about the Binary Search Tree (BST) and its various operations. We have
successfully implemented and understood how to insert nodes, search for elements, and display a
binary search tree. We also performed the deletion operation for different cases, ensuring that the
BST property is maintained..
Group D
Experiment no. 4
Problem Statement:
Construct an expression tree from the given prefix expression, e.g., +--a*bc/def, traverse it
using post-order traversal (non-recursive), and then delete the entire tree.
Objectives:
1. Understand how to represent and manipulate expressions using trees.
2. Implement tree traversal algorithms (specifically non-recursive postorder traversal).
3. Use a stack to construct a binary expression tree from prefix notation.
4. Perform delete operation on binary trees.

Software and Hardware requirements:


Softwares:
 Operating System: 64-bit windows or Linux
 Programming Tools: Python IDE(Spyder/PiCharm/Vscode)
Hardwares:
 Dual-core /higher core processor(I3/I5)
 4/8GB RAM

Theory:
I. Tree:
Tress represents the nodes connected by edge also a class of graphs that is acyclic is termed as
tree> Let us now discuss an important class of graphs called trees and its associated terminology.
Trees are useful in describing any structure that involves hierarchy. Familiar examples of such
structure are family tree, the hierarchy of positions in an organization ans so on.
II. Expression Binary Tree:
The expression tree is a binary tree in which each internal node corresponds to the
operator and each leaf node corresponds to the operand so for example expression tree
for 3 + ((5+9)*2) would be:
III. Construction of Expression Tree:
Now For constructing an expression tree we use a stack. We loop through input expressions and
do the following for every character.
1. If a character is an operand push that into the stack
2. If a character is an operator, pop two values from the stack, make push the current node again.

IV. Use of Expression tree:


1. The main objective of using the expression trees is to make complex expressions
and can be easily evaluated using these expression trees.
2. It is also used to find out the associativity of each operator in the expression.
3. It is also used to solve the postfix, prefix, and infix expression evaluation.
[Link]
A traversal is a process that visits all the nodes in the tree. Since a tree is a
nonlinear data structure, there is no unique traversal. We will consider several
traversal algorithms with we group in the following two kinds
•depth-first traversal
•breadth-first traversal
There are three different types of depth-first traversals, :
•PreOrder traversal - visit the parent first and then left and right children;
•InOrder traversal - visit the left child, then the parent and the right child;
•PostOrder traversal - visit left child, then the right child and then the parent;
There is only one kind of breadth-first traversal--the level order traversal. This
traversal visits nodes by levels from top to bottom and from left to right.
As an example consider the
following tree and its four traversals:
PreOrder - 8, 5, 9, 7, 1, 12, 2, 4, 11, 3
InOrder - 9, 5, 1, 7, 2, 12, 8, 4, 3, 11
PostOrder - 9, 1, 2, 12, 7, 5, 3, 11, 4, 8
LevelOrder - 8, 5, 4, 9, 7, 11, 1, 12, 3, 2
Algorithm to insert a node :
Step 1 - Search for the node whose child node is to be inserted. This is a node at some level i,
and a node is to be inserted at the level i +1 as either its left child or right child. This is the node
after which the insertion is to be made.
Step 2 - Link a new node to the node that becomes its parent node, that is, either
the Lchild or the Rchild.
Delete operation on Binary Tree:
Algorithm:
● Starting at the root, find the deepest and rightmost node in the binary tree
and node which we want to delete.
● Replace the deepest rightmost node’s data with the node to be deleted.
● Then delete the deepest rightmost node.
1) Node to be deleted is the leaf: Simply remove from the tree.
2) Node to be deleted has only one child: Copy the child to the node and delete the
Child

3) Node to be deleted has two children: Find inorder successor of the node. Copy contents of
the inorder successor to the node and delete the inorder successor. Note that inorder
predecessor can also be used

Algorithm: Write as per code by yourself

Flowchart: Write as per code by yourself

Conclusion:
The program successfully constructs an Expression Tree from a Prefix Expression, performs non-
recursive postorder traversal, and deletes the entire tree. This demonstrates the practical use of
Stacks and Binary Trees in expression evaluation.

Common questions

Powered by AI

Binary search trees (BSTs) offer several advantages over simple arrays for managing datasets. They maintain elements in sorted order, which allows for efficient search operations with an average-time complexity of O(log n), while searching in an array would have O(n) in the worst case if it is unsorted. The hierarchical structure of a BST optimizes insertion and deletion operations, which, similar to search operations, have average time complexities of O(log n). However, if the BST becomes unbalanced, the complexity can degrade to O(n), comparable to an array's worst case. Despite this, balanced variations like AVL trees maintain the O(log n) efficiency .

Implementing a hash table with linear probing is advantageous in scenarios where memory overhead minimization is crucial, as it avoids pointers required by separate chaining. Linear probing simplifies the table structure by handling collisions directly within the array, benefitting cache performance due to memory locality. However, the trade-offs include handling clustering issues, which can degrade performance to O(n) in worst cases, and complicated deletion processes. Balancing is critical to mitigate these drawbacks by maintaining a low load factor .

The time complexity of searching in a binary search tree degrades from O(log n) to O(n) when the tree becomes unbalanced, resulting in skewed structures resembling linked lists. This occurs when insertions are sequentially ordered without rearrangement, leading to inefficient operations. To mitigate this, self-balancing trees like AVL or Red-Black Trees, which automatically adjust to remain balanced, maintain O(log n) operations, preserving performance by distributing nodes evenly .

The choice of hash function significantly impacts the performance of hash tables. The division method, which computes the hash index as 'key mod table_size,' ensures the indices remain within table limits but the function needs to be well-chosen to distribute keys uniformly to avoid clustering. Collision resolution techniques also affect performance: chaining handles collisions by storing keys in a linked list at the index, maintaining average time complexity of O(1), whereas linear probing places keys in subsequent empty slots, risking clustering and performance degradation to O(n) if not managed .

To compute the average number of books borrowed per library member efficiently, maintain a running total of all borrow counts and the total number of members, which allows the average to be calculated in O(1) time by dividing the total borrow count by the number of members. Using Python's data structures like dictionaries can facilitate storage of borrow data per member, allowing fast lookup and update operations to adjust totals as records are added or removed .

Chaining resolves hash table collisions by allowing each bucket to contain a separate linked list to manage multiple key-value pairs that hash to the same index. This approach contrasts with linear probing, which handles collisions by finding the next available slot linearly, potentially leading to clustering issues. Chaining maintains constant average-time complexity (O(1)) for operations and significantly reduces primary clustering, although it may incur overhead in space and handling linked list data structures .

Level-order traversal of a binary tree is beneficial for applications requiring breadth-first exploration, such as debugging tree structures or databases, as it explores nodes layer by layer, which aligns with many operational requirements. Implementing this involves using a queue to track nodes by their levels, adding complexity in space due to queue storage requirements, especially for wide trees where entire levels may need queuing at once. Despite this, its systematic nature provides clear insights into tree level structures, making it vital for comprehensive analysis and manipulation .

Non-recursive traversal methods, such as using stacks, affect expression tree implementation by avoiding the overhead associated with recursive function calls, which can be resource-intensive for deep trees due to call stack limitations. This method makes traversal in fixed memory size possible and can improve performance by preventing stack overflow in environments with limited stack sizes. However, it requires extra coding complexity to simulate the call stack and manage node visits explicitly .

In a queue management system, event prioritization can significantly enhance efficiency by ensuring critical tasks are processed first, potentially avoiding bottlenecks in real-time processing. Without prioritization, a standard first-in-first-out (FIFO) queue might lead to undesirable latencies for urgent events when lower priority events occupy the front, affecting overall system responsiveness. Implementing priority queues, where elements have priority levels, can alleviate such issues, allowing a trade-off between complexity and efficiency to match system requirements .

Using stacks for undo/redo functionality in text editing systems efficiently manages state changes by maintaining a LIFO (Last In, First Out) order. The stack structure allows easy push of new changes and pop of recent actions, enabling quick undo and redo operations. However, limitations include memory use for large states and reliance on linear undo sequences—non-linear or partial undo is complex to implement. Furthermore, large or numerous operations can lead to performance overhead, especially if not efficiently managed .

You might also like