DSA Project
DSA Project
(DSEU)
Department of B.Tech (Data Analytics)
Bhai Parmanand DSEU Shakarpur Campus-II
Practical File
Semester: 2
Subject: DATA STRUCTURES
Session: 2024-28 Code:
DTA-3-203-T
INDEX
S.No. Practical List Date Teacher’s
2
Sign
a. Aim
4
b. Algorithm
1. Initialize an array.
2. Perform insertion by adding elements at a specific index.
3. Perform deletion by removing elements by value or index.
4. Search an element by iterating through the array.
5. Traverse the array and display each element.
3. Program
def display(arr):
print("Array elements:", arr)
def insert(arr, element, index):
arr.insert(index, element)
def delete(arr, element):
if element in arr:
arr.remove(element)
def search(arr, element):
return element in arr
# Initial array
arr = [10, 20, 30, 40, 50]
display(arr)
insert(arr, 25, 2)
print("After insertion:")
display(arr)
delete(arr, 30)
print("After deletion:")
display(arr)
print("Is 40 in array?", search(arr, 40))
4. Output
a. Aim
b. Algorithm
1. Initialize a 2D array.
2. Traverse the array row by row and print the elements.
3. Update a specific element by index.
3. Program
def display(matrix):
print("2D Array:")
for row in matrix:
print(row)
# Initialize 2D array
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
display(matrix)
# Update value
matrix[1][1] = 10
print("After update:")
display(matrix)
4. Output
2D Array:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
After update:
2D Array:
[1, 2, 3]
[4, 10, 6]
[7, 8, 9]
a. Aim
To check if a given matrix is a sparse matrix (i.e., most of its elements are
zero).
6
b. Algorithm
1. Initialize a matrix.
2. Count the number of zero elements.
3. If zero elements > half of total elements, it's sparse.
3. Program
def is_sparse(matrix):
zero_count = 0
total_elements = len(matrix) * len(matrix[0])
matrix = [
[0, 0, 3],
[0, 0, 0],
[1, 0, 0]
]
if is_sparse(matrix):
print("The matrix is a sparse matrix.")
else:
print("The matrix is not a sparse matrix.")
4. Output
a. Aim
b. Algorithm
7
3. Program
class Node:
def __init__(self, data):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
def traverse(self):
temp = self.head
while temp:
print(temp.data, end=" -> ")
temp = temp.next
print("None")
8
ll = SinglyLinkedList()
ll.insert(10)
ll.insert(20)
ll.insert(30)
print("Traversal:")
ll.traverse()
ll.delete(20)
print("After Deletion:")
ll.traverse()
4. Output
Traversal:
10 -> 20 -> 30 -> None
After Deletion:
10 -> 30 -> None
a. Aim
b. Algorithm
3. Program
class Node:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class DoublyLinkedList:
def __init__(self):
self.head = None
def traverse(self):
temp = self.head
while temp:
print(temp.data, end=" <-> ")
temp = temp.next
print("None")
dll = DoublyLinkedList()
10
dll.insert(1)
dll.insert(2)
dll.insert(3)
print("Traversal:")
dll.traverse()
dll.delete(2)
print("After Deletion:")
dll.traverse()
4. Output
Traversal:
1 <-> 2 <-> 3 <-> None
After Deletion:
1 <-> 3 <-> None
a. Aim
b. Algorithm
3. Program
class Node:
def __init__(self, data):
self.data = data
11
self.next = None
class CircularLinkedList:
def __init__(self):
self.tail = None
def traverse(self):
if not self.tail:
print("List is empty")
return
current = self.tail.next
while True:
12
cll = CircularLinkedList()
cll.insert(10)
cll.insert(20)
cll.insert(30)
print("Traversal:")
cll.traverse()
cll.delete(20)
print("After Deletion:")
cll.traverse()
4. Output
Traversal:
10 -> 20 -> 30 -> (back to start)
After Deletion:
10 -> 30 -> (back to start)
a. Aim
b. Algorithm
3. Program
stack = []
def push(item):
stack.append(item)
print(f"Pushed {item}")
def pop():
13
if stack:
item = stack.pop()
print(f"Popped {item}")
else:
print("Stack is empty")
push(10)
push(20)
push(30)
print("Stack:", stack)
pop()
print("Stack after pop:", stack)
4. Output
Pushed 10
Pushed 20
Pushed 30
Stack: [10, 20, 30]
Popped 30
Stack after pop: [10, 20]
a. Aim
b. Algorithm
3. Program
def is_operator(c):
return c in "+-*/^"
def precedence(op):
if op == '+' or op == '-':
return 1
if op == '*' or op == '/':
return 2
if op == '^':
14
return 3
return 0
def infix_to_prefix(expression):
def reverse(expr):
expr = expr[::-1]
expr = ['(' if c == ')' else ')' if c == '(' else c for c in expr]
return ''.join(expr)
def infix_to_postfix(expr):
stack = []
result = []
for c in expr:
if c.isalnum():
result.append(c)
elif c == '(':
stack.append(c)
elif c == ')':
while stack and stack[-1] != '(':
result.append(stack.pop())
stack.pop()
else:
while stack and precedence(c) <= precedence(stack[-1]):
result.append(stack.pop())
stack.append(c)
while stack:
result.append(stack.pop())
return ''.join(result)
reversed_expr = reverse(expression)
postfix = infix_to_postfix(reversed_expr)
return postfix[::-1]
expr = "A+B*C"
print("Infix:", expr)
print("Prefix:", infix_to_prefix(expr))
4. Output
Infix: A+B*C
Prefix: +A*BC
15
a. Aim
b. Algorithm
3. Program
def precedence(op):
if op == '+' or op == '-':
return 1
if op == '*' or op == '/':
return 2
if op == '^':
return 3
return 0
def infix_to_postfix(expression):
stack = []
result = ""
for c in expression:
16
if c.isalnum():
result += c
elif c == '(':
stack.append(c)
elif c == ')':
while stack and stack[-1] != '(':
result += stack.pop()
stack.pop()
else:
while stack and precedence(c) <= precedence(stack[-1]):
result += stack.pop()
stack.append(c)
while stack:
result += stack.pop()
return result
expr = "A+B*C"
print("Infix:", expr)
print("Postfix:", infix_to_postfix(expr))
4. Output
Infix: A+B*C
Postfix: ABC*+
17
a. Aim
To implement the Ackermann function for given values of m and n using
recursion.
b. Algorithm
o If m == 0 → return n + 1
c. Program
if m == 0:
return n + 1
return ackermann(m - 1, 1)
d. Output
Ackermann(2, 3): 9
a. Aim
To demonstrate mutual recursion using two functions that call each other.
b. Algorithm
c. Program
def is_even(n):
if n == 0:
return True
else:
return is_odd(n - 1)
def is_odd(n):
if n == 0:
return False
else:
return is_even(n - 1)
num = 4
d. Output
Is 4 even?: True
Is 4 odd?: False
a. Aim
To implement enqueue and dequeue operations on a queue using both
array and linked list.
b. Algorithm
Array Implementation:
c. Program
queue_array = []
def enqueue_array(item):
queue_array.append(item)
def dequeue_array():
if queue_array:
else:
print("Queue is empty")
enqueue_array(1)
enqueue_array(2)
dequeue_array()
20
class Node:
self.data = data
self.next = None
class Queue:
def __init__(self):
new_node = Node(item)
if not self.rear:
else:
self.rear.next = new_node
self.rear = new_node
def dequeue(self):
if not self.front:
print("Queue is empty")
return
self.front = self.front.next
if not self.front:
self.rear = None
q = Queue()
21
q.enqueue(10)
q.enqueue(20)
q.dequeue()
d. Output
Enqueued (Array): 1
Enqueued (Array): 2
Dequeued (Array): 1
Enqueued (LL): 10
Enqueued (LL): 20
Dequeued (LL): 10
22
a. Aim
To implement a Priority Queue where elements are dequeued based on
priority.
b. Algorithm
c. Program
class PriorityQueue:
def __init__(self):
self.queue = []
self.queue.append((priority, item))
def dequeue(self):
if self.queue:
return self.queue.pop(0)[1]
else:
pq = PriorityQueue()
pq.enqueue("Task 1", 3)
pq.enqueue("Task 2", 1)
pq.enqueue("Task 3", 2)
print("Dequeued:", pq.dequeue())
23
print("Dequeued:", pq.dequeue())
print("Dequeued:", pq.dequeue())
d. Output
Dequeued: Task 2
Dequeued: Task 3
Dequeued: Task 1
a. Aim
To implement a deque allowing insertion and deletion from both ends.
b. Algorithm
1. Use collections.deque.
c. Program
dq = deque()
dq.append(10)
dq.appendleft(5)
dq.append(15)
dq.pop()
dq.popleft()
d. Output
less
Edit
a. Aim
To perform inorder, preorder, and postorder traversals on a binary tree.
25
b. Algorithm
c. Program
python
Edit
class Node:
self.left = None
self.right = None
self.data = key
def inorder(root):
if root:
inorder(root.left)
inorder(root.right)
def preorder(root):
if root:
preorder(root.left)
preorder(root.right)
def postorder(root):
if root:
postorder(root.left)
26
postorder(root.right)
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
print("Inorder traversal:")
inorder(root)
print("\nPreorder traversal:")
preorder(root)
print("\nPostorder traversal:")
postorder(root)
d. Output
Inorder traversal:
42513
Preorder traversal:
12453
Postorder traversal:
45231
a. Aim
To perform insertion, search, and traversal operations on a Binary Search
Tree (BST).
b. Algorithm
2. Insert a node:
c. Program
class Node:
self.data = key
if root is None:
return Node(key)
else:
return root
def inorder(root):
if root:
inorder(root.left)
inorder(root.right)
return root
28
root = Node(50)
insert(root, 30)
insert(root, 70)
insert(root, 20)
insert(root, 40)
insert(root, 60)
print("Inorder traversal:")
inorder(root)
d. Output
Inorder traversal:
20 30 40 50 60 70
a. Aim
To implement an AVL Tree with automatic balancing on insertion.
b. Algorithm
c. Program
class Node:
self.data = key
self.height = 1
def height(n):
def get_balance(n):
def right_rotate(y):
x = y.left
T2 = x.right
x.right = y
y.left = T2
return x
def left_rotate(x):
y = x.right
T2 = y.left
y.left = x
x.right = T2
return y
if not root:
return Node(key)
else:
balance = get_balance(root)
# Balancing
return right_rotate(root)
return left_rotate(root)
root.left = left_rotate(root.left)
return right_rotate(root)
root.right = right_rotate(root.right)
return left_rotate(root)
return root
def preorder(root):
if root:
31
preorder(root.left)
preorder(root.right)
root = None
preorder(root)
d. Output
30 20 10 25 40 50
a. Aim
To implement a graph using adjacency list representation.
b. Algorithm
1. Use a dictionary where keys are nodes and values are lists of
adjacent nodes.
c. Program
class Graph:
def __init__(self):
self.graph = {}
32
if u in self.graph:
self.graph[u].append(v)
else:
self.graph[u] = [v]
def display(self):
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(2, 3)
g.add_edge(3, 3)
g.display()
d. Output
0 -> [1, 2]
1 -> [2]
2 -> [0, 3]
3 -> [3]
33
19. Graph Traversal: Depth First Search (DFS) and Breadth First
Search (BFS)
a. Aim
To implement DFS and BFS traversal algorithms for a graph.
b. Algorithm
DFS:
2. Mark it visited.
BFS:
o Dequeue a node.
34
c. Program
class Graph:
def __init__(self):
self.graph = {}
if u not in self.graph:
self.graph[u] = []
self.graph[u].append(v)
visited.add(v)
self.dfs_util(neighbor, visited)
visited = set()
print("DFS Traversal:")
self.dfs_util(start, visited)
print()
visited = set()
queue = deque([start])
35
visited.add(start)
print("BFS Traversal:")
while queue:
v = queue.popleft()
visited.add(neighbor)
queue.append(neighbor)
print()
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(2, 3)
g.add_edge(3, 3)
g.dfs(2)
g.bfs(2)
d. Output
DFS Traversal:
2013
BFS Traversal:
2031
36
a. Aim
To search a desired element in an array using the Linear Search algorithm.
b. Algorithm
c. Program
for i in range(len(arr)):
if arr[i] == key:
return i
return -1
37
arr = [5, 8, 1, 6, 9]
key = 6
d. Output
a. Aim
To search a desired element in a sorted array using Binary Search.
b. Algorithm
c. Program
low = 0
high = len(arr) - 1
if arr[mid] == key:
return mid
low = mid + 1
else:
high = mid - 1
return -1
key = 7
Algorithm:
1. Start from the first element, compare it with the next element.
Program:
def bubble_sort(arr):
n = len(arr)
for i in range(n):
swapped = False
swapped = True
if not swapped:
break
bubble_sort(arr)
Output:
Algorithm:
Program:
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
left = arr[:mid]
right = arr[mid:]
merge_sort(left)
merge_sort(right)
i=j=k=0
40
arr[k] = left[i]
i += 1
else:
arr[k] = right[j]
j += 1
k += 1
arr[k] = left[i]
i += 1
k += 1
arr[k] = right[j]
j += 1
k += 1
merge_sort(arr)
Output:
Algorithm:
Program:
def selection_sort(arr):
for i in range(len(arr)):
min_idx = i
min_idx = j
selection_sort(arr)
Output:
Algorithm:
2. For each element, place it in the correct position in the sorted part
of the array.
Program:
def insertion_sort(arr):
key = arr[i]
j=i-1
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
insertion_sort(arr)
Output:
Algorithm:
Program:
def shell_sort(arr):
n = len(arr)
gap = n // 2
temp = arr[i]
j=i
j -= gap
arr[j] = temp
gap //= 2
44
shell_sort(arr)
Output:
Algorithm:
2. Partition the array such that elements less than the pivot are on the
left and greater on the right.
Program:
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
arr = [10, 7, 8, 9, 1, 5]
sorted_arr = quick_sort(arr)
Output:
Algorithm:
Program:
# Create a HashTable
hash_table = {}
# Insert elements
hash_table['name'] = 'Alice'
hash_table['age'] = 25
print("HashTable:", hash_table)
print("Age:", hash_table.get('age'))
# Delete a key
del hash_table['city']
46
Output:
Age: 25
Algorithm:
Program:
class HashTable:
self.size = size
i=0
index = self.hash_func(key)
i += 1
index = self.quadratic_probing(key, i)
self.table[index] = key
def display(self):
ht = HashTable(10)
ht.insert(key)
ht.display()
Output:
Hash Table: [None, None, 25, 35, 15, 5, 85, None, None, None]
48
Algorithm:
Program:
class BucketHash:
self.size = size
index = self.hash_func(key)
self.buckets[index].append(key)
def display(self):
bh = BucketHash(5)
bh.insert(key)
bh.display()
Output:
Bucket 2: [7]
Bucket 3: []
Bucket 4: []