0% found this document useful (0 votes)
9 views54 pages

DSD Lab Final

The document contains a list of programming exercises focused on implementing various data structures and algorithms in Python, including simple ADTs, recursive algorithms, and applications of lists, stacks, queues, and graphs. Each exercise outlines the aim, algorithm, coding examples, and results of the implementation. The exercises cover a range of topics such as polynomial addition, infix to postfix conversion, and FCFS CPU scheduling.

Uploaded by

kurinji
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)
9 views54 pages

DSD Lab Final

The document contains a list of programming exercises focused on implementing various data structures and algorithms in Python, including simple ADTs, recursive algorithms, and applications of lists, stacks, queues, and graphs. Each exercise outlines the aim, algorithm, coding examples, and results of the implementation. The exercises cover a range of topics such as polynomial addition, infix to postfix conversion, and FCFS CPU scheduling.

Uploaded by

kurinji
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
You are on page 1/ 54

List of Programs

Ex. No PROGRAMS

1. Implement simple ADTs as Python classes

2. Implement recursive algorithms in Python

3. Implement List ADT using Python arrays

4. Linked list implementations of List

5. Implementation of Stack and Queue ADTs

6a. Application of List

6b. Application of Stack

6c. Application of Queue

7a. Implementation of searching algorithms

7b. Implementation of Sorting Algorithm

8. Implementation of Hash tables

9a. Tree representation

9b. Tree Traversal Algorithms

10. Implementation of Binary Search Trees

11. Implementation of Heaps

12a. Graph representation

12b. Graph Traversal

13. Implementation of single source shortest path algorithm

14. Implementation of minimum spanning tree algorithms


Ex.No:1 Implement simple ADTs as Python classes

Aim:
To Implement simple ADTs as Python classes using Stack,Queue,List using python.

Algorithm:

1. Create a Stack[ ],Queue[],List[] with MAX size as your wish.


2. Write function for all the basic operations of stack,Queue,List - PUSH(), POP() and
DISPLAY(),append(),Extend().
3. Display the output.
4. Close the program

Coding :

Stack:
stack = []
stack.append('a')
stack.append('b')
stack.append('c')
print('Initial stack')
print(stack)
print('\nElements poped from stack:')
print(stack.pop())
print(stack.pop())
print(stack.pop())
print('\nStack after elements are poped:')
print(stack)

Queue:
queue = []
queue.append('a')
queue.append('b')
queue.append('c')
print("Initial queue")
print(queue)
print("\nElements dequeued from queue")
print(queue.pop(0))
print(queue.pop(0))
print(queue.pop(0))
print("\nQueue after removing elements")
print(queue)
List:
List = [1,2,3,4]
print("Initial List: ")
print(List)
List.extend([8, 'Geeks', 'Always'])
print("\nList after performing Extend Operation: ")
print(List)

Output:
Stack:
Initial stack
['a', 'b', 'c']
Elements poped from stack:
c
b
a
Stack after elements are poped:
[]
Queue:
['a', 'b', 'c']
Elements dequeued from queue
a
b
c
Queue after removing elements
[]
List:
Initial List:
[1, 2, 3, 4]
List after performing Extend Operation:
[1, 2, 3, 4, 8, 'Geeks', 'Always']

Result:
Thus the Implementation of simple ADTs Python classes was executed successfully.
Ex.No:2 Implement recursive algorithms in Python

Aim:
To Implement a recursive algorithms in Python using Fibonacci Series

Algorithm:
1. Input the 'n' value until which the Fibonacci series has to be generated
2. Initialize sum = 0, a = 0, b = 1 and count = 1
3. while (count <= n)
4. print sum
5. Increment the count variable
6. swap a and b
7. sum = a + b
8. while (count > n)
9. End the algorithm
10. Else
11. Repeat from steps 4 to 7

Coding:
No = 10
num1, num2 = 0, 1
count = 0
if No <= 0:
print("Invalid Number")
elif No == 1:
print("Fibonacci sequence for limit of ",No,":")
print(num1)
else:
print("Fibonacci sequence:")
while count < No:
print(num1)
nth = num1 + num2
num1 = num2
num2 = nth
count += 1
Output:
Fibonacci sequence:
0
1
1
2
3
5
8
13
21
34

Result:
Thus the Implementation of recursive algorithms in Python using Fibonacci series was
executed successfully.
Ex.No:3 Implement List ADT using Python arrays

Aim:
To Implement List ADT using Python arrays.

Algorithm
1. Using define function initialize the list.
2. While loop to declare the elements until the condition is satisfied.
3. Using convert arr function to convert the elements to an array
4.Stop the program

Coding:
class Node:
def __init__(self, data):
self.data = data
self.next = None

def add(data):
return Node(data)
def printarray(a, n):
i=0
while i < n:
print(a[i], end=" ")
i += 1
print()

def findlength(head):
cur = head
count = 0
while(cur!=None):
count=count+1
cur = cur.next
return count

def convertarr(head):
len = findlength(head)
arr = []
cur = head
while(cur!=None):
arr.append(cur.data)
cur = cur.next
printarray(arr, len)
head = add(6)
head.next = add(4)
head.next.next = add(3)
head.next.next.next = add(4)

convertarr(head)
Output:
[6,4,3,4]

Result:
Thus the implementation of List in arrays was executed successfully.
Ex.NO:4 Linked list implementations of List

Aim:
To Implement the Linked list implementations of List using python

Algorithm:
1. Create a list[ ] with MAX size as your wish.
2. Write function for all the basic operations of list - create(), insert(), deletion(), display().
3.Using append() to extend the elements, removal() to delete the elements
3. Close the program.

Coding:
# Initializing a list
List = [1, 2, 3, 4]
print("Initial List:")
print(List)

# Extending the list


List.extend([8, 'Geeks', 'Always'])
print("\nList after performing Extend Operation:")
print(List)

# Creating a blank list


List = []
print("\nBlank List:")
print(List)

# Creating a new list of numbers


List = [10, 20, 14]
print("\nList of numbers:")
print(List)

# Creating a list of strings


List = ["Geeks", "For", "Geeks"]
print("\nList Items:")
print(List[0]) # First element
print(List[2]) # Third element

# Adding elements using insert()


List = [1, 2, 3, 4]
print("\nInitial List:")
print(List)
List.insert(3, 12) # Inserting 12 at index 3
List.insert(0, 'Geeks') # Inserting 'Geeks' at the beginning
print("\nList after performing Insert Operation:")
print(List)
# Removing elements from a list
List = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
print("\nInitial List:")
print(List)
List.remove(5) # Removing element 5
List.remove(6) # Removing element 6
print("\nList after Removal of two elements:")
print(List)

# Removing a range of elements


for i in range(1, 5): # Removing 1, 2, 3, 4
List.remove(i)
print("\nList after Removing a range of elements:")
print(List)

# Creating a multi-dimensional list


List = [['Geeks', 'For'], ['Geeks']]
print("\nMulti-Dimensional List:")
print(List)
Output:
Initial blank List:
[]
List after Addition of Three elements:
[1, 2, 4]
List after Addition of elements from 1-3:
[1, 2, 4, 1, 2, 3]
>>>
===================== RESTART: Z:/New folder/queue 1.py
=====================
Initial List:
[1, 2, 3, 4]
List after performing Insert Operation:
['Geeks', 1, 2, 3, 12, 4]
>>>
===================== RESTART: Z:/New folder/queue 1.py
=====================
Intial List:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
List after Removal of two elements:
[1, 2, 3, 4, 7, 8, 9, 10, 11, 12]
List after Removing a range of elements:
[7, 8, 9, 10, 11, 12]
Result:
Thus the list was created, inserted, removed and extend the element was executed successfully.
Ex.No:5 Implementation of Stack and Queue ADTs

Aim:
To Implementation of Stack and Queue ADTs

Algorithm:

1. Create a Stack[ ],Queue[] with MAX size as your wish.


2. Write function for all the basic operations of stack - append(), POP()
3. Display the elements poped from the stack and elements dequeued from the queue.
4. Close the program.
Coding:
stack = []
stack.append('a')
stack.append('b')
stack.append('c')
print('Initial stack')
print(stack)
print('\nElements poped from stack:')
print(stack.pop())
print(stack.pop())
print(stack.pop())
print('\nStack after elements are poped:')
print(stack)

Queue:
queue = []
queue.append('a')
queue.append('b')
queue.append('c')
print("Initial queue")
print(queue)
print("\nElements dequeued from queue")
print(queue.pop(0))
print(queue.pop(0))
print(queue.pop(0))
print("\nQueue after removing elements")
print(queue)

Output:
Initial stack
['a', 'b', 'c']
Elements poped from stack:
c
b
a
Stack after elements are poped:
[]

Result:
Thus the program for Implementation of Stack and Queue ADTs executed successfully
Ex.No:6a Application of List

Aim:
To implement list application using Polynomial Addition in python

Algorithm:
1. Using the define function initial elements will be declared.
2. For loop gives the output of sum of the elements
3. print [poly] statement have the sum of two polynomial elements.
4. Close the program

Coding:

def add(A, B, m, n):


size = max(m, n)
sum_poly = [0] * size # Initialize with zeros

# Copy elements from A and B


for i in range(m):
sum_poly[i] = A[i]
for i in range(n):
sum_poly[i] += B[i] # Add corresponding terms of B

return sum_poly

def printPoly(poly, n):


for i in range(n):
if poly[i] == 0:
continue # Skip zero coefficients

if i == 0:
print(poly[i], end="") # First term doesn't need 'x'
else:
print(f" + {poly[i]}x^{i}", end="") # Correct format for terms

print() # Newline after printing the polynomial

# Ensuring correct execution only when run as main script


if __name__ == "__main__":
A = [5, 0, 10, 6] # Represents 5 + 0x + 10x^2 + 6x^3
B = [1, 2, 4] # Represents 1 + 2x + 4x^2
m = len(A)
n = len(B)
print("First polynomial is:")
printPoly(A, m)

print("\nSecond polynomial is:")


printPoly(B, n)

sum_poly = add(A, B, m, n)
size = max(m, n)

print("\nSum polynomial is:")


printPoly(sum_poly, size)

Output:
First polynomial is
5 + 0x^1 + 10x^2 + 6x^3

Second polynomial is
1 + 2x^1 + 4x^2

Sum polynomial is
6 + 2x^1 + 14x^2 + 6x^3

Result:
Thus the program was executed successfully.
Ex.No:6b Application of Stack

Aim:
To implement the conversion of infix to postfix in stack

Algorithm:
1. Read the given expression
2. Check ifempty or not ,the stack will insert the elements. 3.
Using push(),pop() to insert the element or remove the element.
4. Check the operator based on the precedence the expression will be evaluated
5.Close the program

Coding:
class Conversion:
def __init__(self, capacity):
self.top = -1
self.capacity = capacity
self.array = []
self.output = []
self.precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
def isEmpty(self):
return self.top == -1
def peek(self):
return self.array[-1] if not self.isEmpty() else None
def pop(self):
if not self.isEmpty():
self.top -= 1
return self.array.pop()
else:
return "$" # Error indicator
def push(self, op):
self.top += 1
self.array.append(op)
def isOperand(self, ch):
return ch.isalpha() or ch.isdigit() # Allow numbers as well
def notGreater(self, i):
try:
a = self.precedence[i]
b = self.precedence.get(self.peek(), -1) # Avoid KeyError
return a <= b
except KeyError:
return False
def infixToPostfix(self, exp):
for i in exp:
if self.isOperand(i):
self.output.append(i)
elif i == '(':
self.push(i)
elif i == ')':
while (not self.isEmpty()) and self.peek() != '(':
self.output.append(self.pop())
if (not self.isEmpty() and self.peek() == '('):
self.pop() # Remove '(' from stack
else:
while (not self.isEmpty() and self.notGreater(i)):
self.output.append(self.pop())
self.push(i)

while not self.isEmpty():


self.output.append(self.pop())

print("Postfix Expression: " + "".join(self.output))

# Example usage
exp = "a+b*(c^d-e)^(f+g*h)-i"
obj = Conversion(len(exp))
obj.infixToPostfix(exp)

Output:
abcd^e-fgh*+^*+i-

Result:
Thus the conversion can be successfully executed
Ex.No:6c Application of Queue
Aim:
To implement the application of queue using FCFS CPU Scheduling
Algorithm:
1. Input the number of processes required to be scheduled using FCFS, burst time for each
process and its arrival time.

2. Calculate the Finish Time, Turn Around Time and Waiting Time for each process which
in turn help to calculate Average Waiting Time and Average Turn Around Time required
by CPU to schedule given set of process using FCFS.

a. for i = 0, Finish Time T 0 = Arrival Time T 0 + Burst Time T 0

b. for i >= 1, Finish Time T i = Burst Time T i + Finish Time T i - 1

c. for i = 0, Turn Around Time T 0 = Finish Time T 0 - Arrival Time T 0

d. for i >= 1, Turn Around Time T i = Finish Time T i - Arrival Time T i

e. for i = 0, Waiting Time T 0 = Turn Around Time T 0 - Burst Time T 0

f. for i >= 1, Waiting Time T i = Turn Around Time T i - Burst Time T i - 1

3. Process with less arrival time comes first and gets scheduled first by the CPU.

4. Calculate the Average Waiting Time and Average Turn Around Time.
5. Stop the program
Coding:

# Function to calculate waiting time


def findWaitingTime(processes, n, bt, wt):
wt[0] = 0 # First process has no waiting time
for i in range(1, n):
wt[i] = bt[i - 1] + wt[i - 1] # Waiting time formula
# Function to calculate turnaround time
def findTurnAroundTime(processes, n, bt, wt, tat):
for i in range(n):
tat[i] = bt[i] + wt[i] # Turnaround time = burst time + waiting time
# Function to calculate average waiting time and turnaround time
def findavgTime(processes, n, bt):
wt = [0] * n # Waiting time array
tat = [0] * n # Turnaround time array
total_wt = 0
total_tat = 0
# Calculate waiting and turnaround times
findWaitingTime(processes, n, bt, wt)
findTurnAroundTime(processes, n, bt, wt, tat)
print("Processes Burst Time Waiting Time Turnaround Time")
for i in range(n):
total_wt += wt[i]
total_tat += tat[i]
print(f" {i+1}\t\t {bt[i]}\t\t {wt[i]}\t\t {tat[i]}")
print(f"\nAverage Waiting Time = {total_wt / n:.2f}")
print(f"Average Turnaround Time = {total_tat / n:.2f}")
# Driver Code
if __name__ == "__main__":
processes = [1, 2, 3] # Process IDs
n = len(processes)
burst_time = [10, 5, 8] # Burst time for each process
findavgTime(processes, n, burst_time)

Output:
Processes Burst time Waiting time Turn around time
1 10 0 10
2 5 10 15
3 8 15 23

Average waiting time = 8.33333


Average turn around time = 16

Result:
Thus the FCFS CPU Scheduling was Executed Successfully
Ex.No:7A Implementation of searching algorithms
Aim:
To implement searching using Linear and Binary Search algorithm using python
Algorithm:
Linear Search:
1. Read the search element from the user
2. Compare, the search element with the first element in the list
3. If both are matching, then display "Given element found!!!" and terminate the function
4. If both are not matching, then compare search element with the next element in the list.
5. Repeat steps 3 and 4 until the search element is compared with the last element in the list.
6. If the last element in the list is also doesn't match, then display "Element not found!!!" and
terminate the function.

Binary search :
1. Read the search element from the user
2. Find the middle element in the sorted list
3. Compare, the search element with the middle element in the sorted list.
4. If both are matching, then display "Given element found!!!" and terminate the function
5. If both are not matching, then check whether the search element is smaller or larger than
middle element
. 6. If the search element is smaller than middle element, then repeat steps 2, 3, 4 and 5 for the
left sublist of the middle element.
7. If the search element is larger than middle element, then repeat steps 2, 3, 4 and 5 for the right
sublist of the middle element.
8. Repeat the same process until we find the search element in the list or until sublist contains
only one element.
9. If that element also doesn't match with the search element, then display "Element not found in
the list!!!" and terminate the function.

Binary Search Coding:


# Recursive Binary Search Function
def BinarySearch(arr, low, high, key):
if high >= low:
mid = (high + low) // 2
if arr[mid] == key:
return mid
# If the element is smaller than mid, search in the left subarray
elif arr[mid] > key:
return BinarySearch(arr, low, mid - 1, key)
# Otherwise, search in the right subarray
else:
return BinarySearch(arr, mid + 1, high, key)
# Element not found
return -1

# Example usage
arr = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
key = 40

result = BinarySearch(arr, 0, len(arr) - 1, key)


if result != -1:
print(f"{key} found at index {result}")
else:
print(f"{key} not found")

Linear Search Coding:


# Function to perform linear search
def linearsearch(arr, x):
for i in range(len(arr)):
if arr[i] == x:
return i # Return index if found
return -1 # Return -1 if not found

# Example usage
arr = ['t', 'u', 't', 'o', 'r', 'i', 'a', 'l']
x = 'a'

# Perform search and print result


result = linearsearch(arr, x)

if result != -1:
print(f"Element '{x}' found at index {result}")
else:
print(f"Element '{x}' not found in the array")

Output of Binary Search:


40 Found at index 3
Output of Linear Search:
element found at index 6

Result:
Thus the implementation of searching using Linear and Binary Search using python was
executed successfully
Ex.No:7B Implementation of Sorting Algorithm
Aim:
To Implement sorting Algorithm using Quick Sort and Insertion Sort algorithm using python

Algorithm:
Quick Sort:

1. Find a “pivot” item in the array. This item is the basis for comparison for a single
round.
2. Start a pointer (the left pointer) at the first item in the array.
3. Start a pointer (the right pointer) at the last item in the array.
4. While the value at the left pointer in the array is less than the pivot value, move the
left pointer to the right (add 1). Continue until the value at the left pointer is greater
than or equal to the pivot value.
5. While the value at the right pointer in the array is greater than the pivot value, move
the right pointer to the left (subtract 1). Continue until the value at the right pointer is
less than or equal to the pivot value.
6. If the left pointer is less than or equal to the right pointer, then swap the values at
these locations in the array.
7. Move the left pointer to the right by one and the right pointer to the left by one.

Insertion Sort:

1. Compare each element with preceding elements


2. Shift each compared element on the right
3. Place the element at the empty spot
4. Print the sorted array

Coding of Quick Sort:

# Function to partition the array


def partition(arr, low, high):
i = low - 1 # Index of smaller element
pivot = arr[high] # Pivot element

for j in range(low, high):


if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i] # Swap elements

arr[i + 1], arr[high] = arr[high], arr[i + 1] # Swap pivot


return i + 1

# Function to perform QuickSort


def quickSort(arr, low, high):
if low < high:
pi = partition(arr, low, high) # Partitioning index
# Recursively sort elements before and after partition
quickSort(arr, low, pi - 1)
quickSort(arr, pi + 1, high)

# Driver code
arr = [2, 5, 3, 8, 6, 5, 4, 7]
n = len(arr)

quickSort(arr, 0, n - 1)

print("Sorted array is:")


print(*arr) # Prints the sorted array in a clean format

Coding of Insertion Sort:


# Function for Insertion Sort
def insertionSort(arr):
for i in range(1, len(arr)):
key = arr[i]
j=i-1

# Move elements of arr[0..i-1] that are greater than key


while j >= 0 and key < arr[j]:
arr[j + 1] = arr[j]
j -= 1

arr[j + 1] = key # Insert the key in its correct position

# Driver code
arr = ['t', 'u', 't', 'o', 'r', 'i', 'a', 'l']
insertionSort(arr)

# Print sorted array


print("The sorted array is:")
print(*arr) # Using *arr for clean

Output:
Quick Sorted array is:
23455678

The sorted array is:


ailorttu

Result:
Thus the implementation of searching Quick and Insertion Sort algorithm using python was
executed successfully.
Ex.No:8 Implementation of Hash tables
Aim:
To Implement the Hash tables using python
Algorithm:
1. Create a structure, data (hash table item) with key and value as data
2. for loops to define the range within the set of elements.
3. hashfunction(key) for the size of capacity
4. Using insert(),removal() data to be presented or removed.
5. Stop the program
Coding:
# Initialize hash table with empty lists
hashTable = [[] for _ in range(10)]

# Function to check if a number is prime


def checkPrime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1): # Corrected loop range
if n % i == 0:
return False
return True

# Function to get the next prime number greater than n


def getPrime(n):
while not checkPrime(n):
n += 1
return n

# Hash function
def hashFunction(key):
return key % 10 # Simple modulus hash function

# Insert data into the hash table


def insertData(key, data):
index = hashFunction(key)
hashTable[index].append([key, data]) # Append to avoid overwriting

# Remove data by key


def removeData(key):
index = hashFunction(key)
for i, pair in enumerate(hashTable[index]):
if pair[0] == key: # Match key
del hashTable[index][i]
return

# Insert data into the hash table


insertData(123, "apple")
insertData(432, "mango")
insertData(213, "banana")
insertData(654, "guava")

# Print the hash table before deletion


print("Hash Table Before Deletion:")
print(hashTable)

# Remove a key
removeData(123)

# Print the hash table after deletion


print("\nHash Table After Deletion:")
print(hashTable)

Output:
[[], [], [123, 'apple'], [432, 'mango'], [213, 'banana'], [654, 'guava'], [], [], [], []]
[[], [], 0, [432, 'mango'], [213, 'banana'], [654, 'guava'], [], [], [], []]

Result:
Thus the Implementation of hashing was executed successfully
Ex.No:9a Tree representation
Aim:
To implement tree representation in binary tree format
Algorithm:
1. Create a binary tree.
2. Initially all the left and right vertex are none , then declare the values using insert()
function.3.If data>right element place the element in right
4.If data<left element place the element in left
5.prin the tree
6. Stop the program
Coding:
# Class representing a Node in a Binary Search Tree (BST)
class Node:
def __init__(self, data): # Fixed constructor method
self.left = None
self.right = None
self.data = data

# Insert function to add nodes to the BST


def insert(self, data):
if self.data:
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.data = data # Handles empty tree case

# Print the BST in In-Order Traversal


def PrintTree(self):
if self.left:
self.left.PrintTree()
print(self.data) # Fixed print statement
if self.right:
self.right.PrintTree()

# Driver Code to test BST


root = Node(12)
root.insert(6)
root.insert(14)
root.insert(3)
print("In-Order Traversal of the BST:")
root.PrintTree()

Output:
In-Order Traversal of the BST:
3
6
12
14

Result:
Thus the binary tree representation was successfully created
Ex.No:9b Tree Traversal Algorithms

Aim: To Implement traversal using Inorder,Preorder,Postorder techniques.


Algorithm:
Inorder(tree)
 Traverse the left subtree, i.e., call Inorder(left-subtree)
 Visit the root.
 Traverse the right subtree, i.e., call Inorder(right-subtree)

Preorder(tree)
 Visit the root.
 Traverse the left subtree, i.e., call Preorder(left-subtree)
 Traverse the right subtree, i.e., call Preorder(right-subtree)
Postorder(tree)
 Traverse the left subtree, i.e., call Postorder(left-subtree)
 Traverse the right subtree, i.e., call Postorder(right-subtree)
 Visit the root
Coding:
# Node class representing a single node in a Binary Tree
class Node:
def __init__(self, key): # Fixed constructor
self.left = None
self.right = None
self.val = key

# Function to print Inorder Traversal


def printInorder(root):
if root:
printInorder(root.left) # Traverse left subtree
print(root.val) # Visit node
printInorder(root.right) # Traverse right subtree

# Function to print Postorder Traversal


def printPostorder(root):
if root:
printPostorder(root.left) # Traverse left subtree
printPostorder(root.right) # Traverse right subtree
print(root.val) # Visit node
# Function to print Preorder Traversal
def printPreorder(root):
if root:
print(root.val) # Visit node
printPreorder(root.left) # Traverse left subtree
printPreorder(root.right) # Traverse right subtree

# Driver Code to test tree traversal


root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)

# Printing different tree traversals


print("\nPreorder traversal of binary tree is")
printPreorder(root)
print("\nInorder traversal of binary tree is")
printInorder(root)
print("\nPostorder traversal of binary tree is")
printPostorder(root)

Output:
Preorder traversal of binary tree is
1
2
4
5
3
Inorder traversal of binary tree is
4
2
5
1
3
Postorder traversal of binary tree is
4
5
2
3
1

Result:
Thus the Implementation of traversal using Inorder,Preorder,Postorder techniques was executed
successfully
Ex.No:10 Implementation of Binary Search Trees
Aim:
To Implement the Binary Search Trees using python
Algorithm:

1. Read the search element from the user.


2. Compare the search element with the value of root node in the tree.
3. If both are matched, then display "Given node is found!!!" and terminate the function
4. If both are not matched, then check whether search element is smaller or larger than thatnode
value.
5. If search element is smaller, then continue the search process in left subtree.
6. If search element is larger, then continue the search process in right subtree.
7. Repeat the same until we find the exact element or until the search element is comparedwith the
leaf node
8. If we reach to the node having the value equal to the search value then display "Elementis found"
and terminate the function.

Coding:
class Node:
def __init__(self, data): # Fixed constructor
self.left = None
self.right = None
self.data = data

# Insert function to add nodes to the BST


def insert(self, data):
if self.data:
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.data = data # Handles empty tree case

# Function to search for a value in BST


def findval(self, lkpval):
if lkpval < self.data:
if self.left is None:
return str(lkpval) + " Not Found"
return self.left.findval(lkpval)
elif lkpval > self.data:
if self.right is None:
return str(lkpval) + " Not Found"
return self.right.findval(lkpval)
else:
return str(self.data) + " is found"
# Print the BST in In-Order Traversal
def PrintTree(self):
if self.left:
self.left.PrintTree()
print(self.data) # Fixed print syntax
if self.right:
self.right.PrintTree()

# Driver Code to test BST


root = Node(12)
root.insert(6)
root.insert(14)
root.insert(3)

# Search for a value


print(root.findval(7)) # Should return "7 Not Found"
print(root.findval(6)) # Should return "6 is found"

Output:

7 Not Found
6 is found

Result:
Thus the Implementation of Binary Search Trees using python was executed successfully.
Ex.NO:11 Implementation of Heaps
Aim:
To Implement the Heap algorithm using python
Algorithm:
1. Insert the heap function in the list
2. using heappush(),heappop(),heapify() to insert ,delete,display the elements.
3.Stop the program
Coding:
import heapq

# Initializing list
H = [21, 1, 45, 78, 3, 5]

# Converting list into a heap


heapq.heapify(H)
print("Heap after heapify:", H)

# Adding an element to the heap


heapq.heappush(H, 8)
print("Heap after pushing 8:", H)

# Removing the smallest element from the heap


heapq.heappop(H)
print("Heap after popping the smallest element:", H)

Output:

Heap after heapify: [1, 3, 5, 78, 21, 45]


Heap after pushing 8: [1, 3, 5, 78, 21, 45, 8]
Heap after popping the smallest element: [3, 8, 5, 78, 21, 45]

Result:
Thus the Implementation of the Heap algorithm was executed succeefully.
Ex.No:12a Graph representation

Aim:
To implement the graph representation using python
Algorithm:

Graph Representation Coding:

class Graph:
def __init__(self, gdict=None):
if gdict is None:
gdict = {}
self.gdict = gdict
def getVertices(self):
return list(self.gdict.keys())
def edges(self):
return self.findedges()
def findedges(self):
edgename = []
for vrtx in self.gdict:
for nxtvrtx in self.gdict[vrtx]:
if (nxtvrtx, vrtx) not in edgename and (vrtx, nxtvrtx) not in edgename:
edgename.append((vrtx, nxtvrtx))
return edgename

# Graph representation
graph_elements = {"a": ["b", "c"],"b": ["a", "d"],"c": ["a", "d"],"d": ["e"],"e": ["d"] }

# Creating Graph Object


g = Graph(graph_elements)

# Printing vertices
print("Vertices:", g.getVertices())

# Printing edges
print("Edges:", g.edges())

Output:

Vertices: ['a', 'b', 'c', 'd', 'e']


Edges: [('a', 'b'), ('a', 'c'), ('b', 'd'), ('c', 'd'), ('d', 'e')]

Result:
Thus the implementation of graphs was executed successfully.
Ex.No:12b Graph Traversal
Algorithms Aim:
To Implement using BFS,DFS can be traversed.
Algorithm:
DFS:

Step 1 - Define a Stack of size total number of vertices in the graph.

Step 2 - Select any vertex as starting point for traversal. Visit that vertex and push it on to the
Stack.

Step 3 - Visit any one of the non-visited adjacent vertices of a vertex which is at the top of stack
and push it on to the stack.

Step 4 - Repeat step 3 until there is no new vertex to be visited from the vertex which is at the top
of the stack.

Step 5 - When there is no new vertex to visit then use back tracking and pop one vertex from the
stack.

Step 6 - Repeat steps 3, 4 and 5 until stack becomes Empty.

Step 7 - When stack becomes Empty, then produce final spanning tree by removing unused edges
from the graph

BFS:
Step 1 - Define a Queue of size total number of vertices in the graph.

Step 2 - Select any vertex as starting point for traversal. Visit that vertex and insert it into the
Queue.

Step 3 - Visit all the non-visited adjacent vertices of the vertex which is at front of the Queue and
insert them into the Queue.

Step 4 - When there is no new vertex to be visited from the vertex which is at front of the Queue
then delete that vertex.

Step 5 - Repeat steps 3 and 4 until queue becomes empty.

Step 6 - When queue becomes empty, then produce final spanning tree by removing unused edges
from the graph
Coding:
BFS
import collections
def bfs(graph, root):
visited, queue = set(), collections.deque([root])
visited.add(root)
while queue:
vertex = queue.popleft()
print(str(vertex) + " ", end="")
for neighbour in graph[vertex]:
if neighbour not in visited:
visited.add(neighbour)
queue.append(neighbour)
if __name__ == "__main__":
graph = {0: [1, 2], 1: [2], 2: [3], 3: [1, 2] }
print("Following is Breadth First Traversal: ")
bfs(graph, 0)

Output:
Following is Breadth First Traversal:
0123
DFS Coding:
import sys

def ret_graph():
return {
'A': {'B': 5.5, 'C': 2, 'D': 6},
'B': {'A': 5.5, 'E': 3},
'C': {'A': 2, 'F': 2.5},
'D': {'A': 6, 'F': 1.5},
'E': {'B': 3, 'J': 7},
'F': {'C': 2.5, 'D': 1.5, 'K': 1.5, 'G': 3.5},
'G': {'F': 3.5, 'I': 4},
'H': {'J': 2},
'I': {'G': 4, 'J': 4},
'J': {'H': 2, 'I': 4},
'K': {'F': 1.5}
}

start = 'A'
dest = 'J'
visited = []
stack = []
graph = ret_graph()
path = []

stack.append(start)
visited.append(start)

while stack:
curr = stack.pop()
path.append(curr)

if curr == dest:
print("FOUND:", curr)
print("Path:", path)
sys.exit(0) # Exit when the destination is found

for neigh in graph[curr]:


if neigh not in visited:
visited.append(neigh)
stack.append(neigh)

print("Not found")
print("Path:", path)

Output:
FOUND: J
['A', 'D', 'F', 'G', 'I']

Result:
Thus the implementation of using BFS,DFS graph can be traversed.
Ex.No:13 Implementation of single source shortest path algorithm
Aim:
To Implement single source shortest path algorithm using Bellman Ford Algorithm
Algorithm:

1) This step initializes distances from source to all vertices as infinite and distance to source
itself as 0. Create an array dist[] of size |V| with all values as infinite except dist[src] where src is
source vertex.
2) This step calculates shortest distances. Do following |V|-1 times where |V| is the number of
vertices in given graph.
3) Do following for each edge u-v
If dist[v] > dist[u] + weight of edge uv, then update dist[v]
dist[v] = dist[u] + weight of edge uv
4) This step reports if there is a negative weight cycle in graph. Do following for each edge u-v
If dist[v] > dist[u] + weight of edge uv, then “Graph contains negative weight cycle”
The idea of step 3 is, step 2 guarantees shortest distances if graph doesn’t contain negative
weight cycle. If we iterate through all edges one more time and get a shorter path for any vertex,
then there is a negative weight cycle

Coding:
from sys import maxsize

def BellmanFord(graph, V, E, src):


# Step 1: Initialize distances
dis = [maxsize] * V
dis[src] = 0

# Step 2: Relax all edges |V| - 1 times


for _ in range(V - 1):
for j in range(E):
u, v, weight = graph[j]
if dis[u] != maxsize and dis[u] + weight < dis[v]:
dis[v] = dis[u] + weight

# Step 3: Check for negative weight cycles


for j in range(E):
u, v, weight = graph[j]
if dis[u] != maxsize and dis[u] + weight < dis[v]:
print("Graph contains negative weight cycle")
return # Exit if negative cycle found

# Print results
print("Vertex Distance from Source")
for i in range(V):
print(f"{i}\t\t{dis[i]}")
if __name__ == "__main__":
V = 5 # Number of vertices
E = 8 # Number of edges
graph = [
[0, 1, -1],
[0, 2, 4],
[1, 2, 3],
[1, 3, 2],
[1, 4, 2],
[3, 2, 5],
[3, 1, 1],
[4, 3, -3]
]

BellmanFord(graph, V, E, 0)

OUTPUT

Vertex Distance from Source


0 0
1 -1
2 2
3 -2
4 1

Result:
Thus the Implementation of single source shortest path algorithm was successfully executed.
Ex.No:14 Implementation of minimum spanning tree algorithms
Aim:
To implement the minimum spanning tree algorithms using Kruskal Algorithm
Algorithm:
1. Label each vertex
2. List the edges in non-decreasing order of weight.
3. Start with the smallest weighted and beginning growing the minimum weighted spanning tree
from this edge.
4. Add the next available edge that does not form a cycle to the construction of the minimum
weighted spanning tree. If the addition of the next least weighted edge forms a cycle, do not use
it.
5. Continue with step 4 until you have a spanning tree.
Coding:
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = []
def add_edge(self, u, v, w):
self.graph.append([u, v, w])
def find(self, parent, i):
if parent[i] == i:
return i
return self.find(parent, parent[i])
def apply_union(self, parent, rank, x, y):
xroot = self.find(parent, x)
yroot = self.find(parent, y)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
else:
parent[yroot] = xroot
rank[xroot] += 1
def kruskal_algo(self):
result = [] # Store the final MST
i, e = 0, 0 # Indices for sorted edges and result count
# Step 1: Sort all edges in increasing order of weight
self.graph = sorted(self.graph, key=lambda item:
item[2])
parent = []
rank = []
# Create V subsets with single elements
for node in range(self.V):
parent.append(node)
rank.append(0)
# Number of edges in MST must be V-1
while e < self.V - 1:
u, v, w = self.graph[i]
i += 1
x = self.find(parent, u)
y = self.find(parent, v)
# If including this edge does not cause a cycle, add it
to the result
if x != y:
e += 1
result.append([u, v, w])
self.apply_union(parent, rank, x, y)
# Print the final MST
print("Edges in the Minimum Spanning Tree (MST):")
for u, v, weight in result:
print(f"{u} - {v}: {weight}")
# Example Usage
g = Graph(6)
g.add_edge(0, 1, 4)
g.add_edge(0, 2, 4)
g.add_edge(1, 2, 2)
g.add_edge(1, 0, 4)
g.add_edge(2, 0, 4)
g.add_edge(2, 1, 2)
g.add_edge(2, 3, 3)
g.add_edge(2, 5, 2)
g.add_edge(2, 4, 4)
g.add_edge(3, 2, 3)
g.add_edge(3, 4, 3)
g.add_edge(4, 2, 4)
g.add_edge(4, 3, 3)
g.add_edge(5, 2, 2)
g.add_edge(5, 4, 3)
g.kruskal_algo()

Output:
1 - 2: 2
2 - 5: 2
2 - 3: 3
3 - 4: 3
0 - 1: 4

Result:
Thus the program was executed successfully.
ADDITIONAL PROGRAMS
1. Implementation of Bubble Sort Algorithm:
Aim:
To Implement sorting Algorithm for Bubble Sort using python.
Algorithm:
1. Create a list arr of n elements.
2. Set n to the length of the array.
3. Iterate through the list n times (i from 0 to n-1).
4. For each pass of the outer loop (i):
 Compare adjacent elements in the list (arr[j] and arr[j + 1]) for all j from 0 to n-i-2.
 If arr[j] > arr[j + 1], swap the two elements.
 After each pass, the largest element in the remaining unsorted portion of the array
will bubble up to its correct position.
5. After n-1 passes, the list will be sorted in ascending order.
6. display The sorted list arr.
Coding:
def bubbleSort(arr):
n = len(arr)
for i in range(n):
swapped = False # Track if a swap occurs
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True # A swap happened
# If no elements were swapped, break the loop (array is already sorted)
if not swapped:
break
arr = [2, 1, 10, 23]
bubbleSort(arr)
print("Sorted array is:")
print(arr) # Directly print the sorted array
Output:
Sorted array is :
1
2
10
23
Result:
Thus the program for bubble sort was executed successfully.
2 Implementation of Selection Sort Algorithm:

Aim:
To Implement sorting Algorithm for Selection Sort using python.
Algorithm:

1. Create a list array of size elements.


2. Set size to the length of the array.
3. Loop through each index s from 0 to size-1:
 At each step, consider the portion of the array starting from index s to the end (size).
 Assume that the first element in this portion (array[s]) is the smallest, and initialize min_idx to
s.
4. Loop through the remaining unsorted portion of the array (from s+1 to size-1):
 If any element array[i] is smaller than array[min_idx], update min_idx to i.
5. After the inner loop finishes, swap the element at array[s] with the element at array[min_idx].
 This ensures that the smallest element in the unsorted portion is moved to the correct
position.
6. After completing the outer loop, the list will be sorted in ascending order.
7. Display The sorted list array.

Coding:

def selectionSort(array, size):


for s in range(size):
min_idx = s
for i in range(s + 1, size):
if array[i] < array[min_idx]:
min_idx = i
(array[s], array[min_idx]) = (array[min_idx], array[s])
data = [ 7, 2, 1, 6 ]
size = len(data)
selectionSort(data, size)
print('Sorted Array in Ascending Order is :')
print(data)

Output:
Sorted Array in Ascending Order is:
[1,2,6,7]
Result:
Thus the program for selection sort was executed successfully.
3 Implementation of Merge Sort Algorithm:

Aim:
To Implement sorting Algorithm for Merge Sort using python.
Algorithm:
1. Create a merge_sort() function
2. Initiate array list and divide it into subarrays.
3. Create copies of the subarrays
4. Create three-pointers that maintain indexes.
5. Pick larger elements and place them in the right position
6. Pick the remaining elements and sort them accordingly
7. The result will be sorted array
8. Print the sorted array.
Coding:
def Merge_Sort(array):
if len(array) > 1:
mid = len(array)//2
Left = array[:mid]
Right = array[mid:]
Merge_Sort(Left)
Merge_Sort(Right)
i=j=k=0
while i < len(Left) and j < len(Right):
if Left[i] < Right[j]:
array[k] = Left[i]
i += 1
else:
array[k] = Right[j]
j += 1
k += 1
while i < len(Left):
array[k] = Left[i]
i += 1
k += 1
while j < len(Right):
array[k] = Right[j]
j += 1
k += 1
def printarray(array):
for i in range(len(array)):
print(array[i], end=" ")
print()
if __name__ == '__main__':
array = [7, 2, 5, 6, 3, 1, 8, 4]
print("Orignal Array is: ", array)
Merge_Sort(array)
print("Sorted array is: ")
printarray(array)

Output:

Orignal Array is: [7, 2, 5, 6, 3, 1, 8, 4]


Sorted array is:
12345678

Result:

Thus the program for merge sort was executed successfully.


4 Infix expression to a Postfix expression :

Aim:
To Implement python program for infix to postfix conversion.
Algorithm:
1. Scan the infix expression from left to right.
2. If the scanned character is an operand, put it in the postfix expression.
3. Otherwise, do the following
 If the precedence of the current scanned operator is higher than the precedence of the
operator on top of the stack, or if the stack is empty, or if the stack contains a ‘(‘, then push
the current operator onto the stack.
 Else, pop all operators from the stack that have precedence higher than or equal to that of the
current operator. After that push the current operator onto the stack.
4. If the scanned character is a ‘(‘, push it to the stack.
5. If the scanned character is a ‘)’, pop the stack and output it until a ‘(‘ is encountered, and
discard both the parenthesis.
6. Repeat steps 2-5 until the infix expression is scanned.
7. Once the scanning is over, Pop the stack and add the operators in the postfix expression until it
is not empty.
8. Finally, print the postfix expression.

Coding:

def prec(c):
if c == '^':
return 3
elif c == '/' or c == '*':
return 2
elif c == '+' or c == '-':
return 1
else:
return -1
def infixToPostfix(s):
st = []
result = ""
for i in range(len(s)):
c = s[i]
if (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '0' and c <= '9'):
result += c
elif c == '(':
st.append('(')
elif c == ')':
while st[-1] != '(':
result += st.pop()
st.pop()
else:
while st and (prec(c) < prec(st[-1]) or prec(c) == prec(st[-1])):
result += st.pop()
st.append(c)
while st:
result += st.pop()
print(result)
exp = "a+b*(c^d-e)^(f+g*h)-i"
infixToPostfix(exp)

Output:

abcd^e-fgh*+^*+i-

Result:

Thus the program for infix to postfix conversion was executed successfully
5 Factorial of a number:
Aim:
To Implement factorial of a number using recursion python
Algorithm:
1. Start
2. Declare a variable n, fact, and i.
3. Now, read the input number given by the user.
4. Initialize variable fact with 1 and i with 1.
5. Repeat until i<=number
Coding:

def factorial(x):
if x == 1 or x == 0:
return 1
else:
return (x * factorial(x-1))
num = 7
# num = int(input("Enter a number: "))
result = factorial(num)
print("The factorial of", num, "is", result)

Output:

The factorial of 7 is 5040

Result:

Thus the program for factorial of a number using recursion was executed successfully
6. Sum of natural numbers using recursion:
Aim:
To Implement Sum of natural numbers using recursion using python.

Algorithm:

1. Begin with the function recurSum(n) where n is the input number.


2. If n <= 1, return the value of n (i.e., return 1 if n = 1 or return 0 if n = 0).
3. Otherwise, return the sum of n and the result of calling recurSum(n - 1). This means recursively
add n to the sum of all numbers less than n down to 1.
4. Repeat the process until n reaches 1 or 0 (the base case).
5. Once the recursion completes, the total sum will be returned.

Coding:

def recurSum(n):
if n <= 1:
return n
return n + recurSum(n - 1)
n=5
print(recurSum(n))

Output
15

Result:

Thus the program for Sum of natural numbers using recursion was executed successfully
7. Python program for dictionary class:

Aim:
To Implement dictionary class using python

Algorithm:

1. Create a class Dictionary.


2. Inside the class, define an empty dictionary data in the __init__() method to store the key-
value pairs.
3. Input: A key k and a value v.Add the key-value pair to the dictionary.
 If the key already exists, update the value with the new value.
4. Input: A key k.
 If the key exists in the dictionary, delete the key-value pair from data.
 If the key does not exist, display a message that the key is not found.
5. Input: A key k.Check if the key exists in the dictionary.
 If the key exists, return the corresponding value.
 If the key does not exist, return a message that the key is not found.
6. Return a list containing all the keys in the dictionary , a list containing all the values in the
dictionary and a list containing all the key-value pairs as tuples (key, value).
7. Iterate through all key-value pairs in the dictionary.
8. Print each key-value pair.

Coding:

class Dictionary:
def __init__(self):
self.data = {}
def add(self, key, value):
self.data[key] = value
print(f"Added {key}: {value}")
def remove(self, key):
if key in self.data:
del self.data[key]
print(f"Removed key: {key}")
else:
print(f"Key '{key}' not found.")
def get(self, key):
return self.data.get(key, "Key not found")
def list_keys(self):
return list(self.data.keys())
def list_values(self):
return list(self.data.values())
def list_key_value_pairs(self):
return list(self.data.items())
def display(self):
if self.data:
print("Current Dictionary:")
for key, value in self.data.items():
print(f"{key}: {value}")
else:
print("Dictionary is empty.")
my_dict = Dictionary()
my_dict.add("name", "John")
my_dict.add("age", 30)
my_dict.add("city", "New York")
my_dict.display()
print("List of Keys:", my_dict.list_keys())
print("List of Values:", my_dict.list_values())
print("List of Key-Value Pairs:", my_dict.list_key_value_pairs())
my_dict.add("country", "USA")
my_dict.display()
Output:
Added name: John
Added age: 30
Added city: New York
Current Dictionary:
name: John
age: 30
city: New York
List of Keys: ['name', 'age', 'city']
List of Values: ['John', 30, 'New York']
List of Key-Value Pairs: [('name', 'John'), ('age', 30), ('city', 'New York')]
Added country: USA
Current Dictionary:
name: John
age: 30
city: New York
country: USA

Result:

Thus the program for dictionary class was executed successfully


8. Python program for Max Heap:

Aim:
To Implement python program for max heap .

Algorithm:

1. Create an empty list h to represent the heap.


2. Call heapify(h) to prepare the list for heap operations (though it has no effect here as the list is
empty).
3. Use the heappush() function to insert elements into the heap.
4. To simulate a max-heap using Python's default min-heap, multiply the values by -1 (negating
the values).
5. The inserted elements are -10, -30, -20, and -400.
6. The root of the heap (smallest element of the negated heap) will be the maximum value in the
simulated max-heap.
7. To get the original maximum value, negate the root element by -h[0] and print it.
8. Print the heap elements, but convert them back to positive by negating them ([-i for i in h]).
9. Use the heappop() function to remove the smallest element from the heap (which corresponds
to the largest element in the simulated max-heap).
10. The heap is automatically re-organized to maintain the heap property after the removal.
11. Print the heap again, converting the negative values back to positive to simulate the original
max-heap.

Coding:

from heapq import heappop, heappush, heapify


h = []
heapify(h)
heappush(h, -10)
heappush(h, -30)
heappush(h, -20)
heappush(h, -400)
print("Max:", -h[0])
print("Heap:", [-i for i in h])
heappop(h)
print("Heap after pop:", [-i for i in h])
Output:
Max: 400
Heap: [400, 30, 20, 10]
Heap after pop: [30, 10, 20]

Result:

Thus the program for max heap was executed successfully


9. Python program for Min Heap:

Aim:
To Implement python program for min heap .
Algorithm:

1. Create an empty list called heap to store the heap elements.


2. Call the heapify() function on the empty list to ensure it is a valid heap (though this has no
effect on an empty list).
3. Use the heappush() function to add elements one by one to the heap.
 When an element is added, the heap property is automatically maintained (smallest element at
the root).
4. Access and print the root of the heap, which is at index 0. This root element is the smallest
element in a min-heap.
5. Loop through the elements in the heap and print each one.
6. Use heappop() to remove and return the smallest element from the heap. This element is
always at the root.
7. After removal, the heap is re-arranged to maintain the heap property.
8. Loop through the remaining elements in the heap and print each one.

Coding:
from heapq import heapify, heappush, heappop
heap = []
heapify(heap)
heappush(heap, 10)
heappush(heap, 30)
heappush(heap, 20)
heappush(heap, 400)
print("Head value of heap : "+str(heap[0]))
print("The heap elements : ")
for i in heap:
print(i, end = ' ')
print("\n")
element = heappop(heap)
print("The heap elements : ")
for i in heap:
print(i, end = ' ')

Output:
Head value of heap : 10
The heap elements :
10 30 20 400
The heap elements :
20 30 400

Result:

Thus the program min heap was executed successfully.

You might also like