0% found this document useful (0 votes)
10 views

DS LAB MANUAL-1 (1)

The document outlines the implementation of various search algorithms including Breadth First Search (BFS), Depth First Search (DFS), A* Algorithm, and Hill Climbing Algorithm, along with a singly linked list and queue operations. Each section provides the aim, procedure, program code, and output results demonstrating successful execution. The document serves as a comprehensive guide for implementing these algorithms and data structures in programming.

Uploaded by

suriyasri2006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

DS LAB MANUAL-1 (1)

The document outlines the implementation of various search algorithms including Breadth First Search (BFS), Depth First Search (DFS), A* Algorithm, and Hill Climbing Algorithm, along with a singly linked list and queue operations. Each section provides the aim, procedure, program code, and output results demonstrating successful execution. The document serves as a comprehensive guide for implementing these algorithms and data structures in programming.

Uploaded by

suriyasri2006
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 69

EX.NO 1.

a Implementation of Uninformed search algorithms (BFS)

AIM:

Write a Program to Implement Breadth First Search.

Procedure:Create a graph with key – value pair.

Assign empty list as visited nodes.

Initialize a queue as queue.

Define the sub program as bfs and passing parameter as visited, graph and
node.

Append the node in to visited and queue.

Creating loop to visit each node in Breadth First Search method.

Print the node which is visited in BFS method.

PROGRAM

Graph = {

‘5’: [‘3’, ‘7’],


1
‘3’: [‘2’, ‘4’],

‘7’: [‘8’],

‘2’: [],

‘4’: [‘8’],

‘8’: []

Visited = [] # List for visited nodes.

Queue = [] # Initialize a queue.

Def bfs(visited, graph, node):

2
Visited.append(node)

Queue.append(node)

While queue: # Creating loop to visit each node

M = queue.pop(0)

Print(m, end=” “)

For neighbour in graph[m]:

If neighbour not in visited:

Visited.append(neighbour)

Queue.append(neighbour)

3
# Driver Code

Print(“Following is the Breadth-First Search”)

Bfs(visited, graph, ‘5’) # function calling

OUTPUT

Following is the Breadth-First Search 5 3 7 2 4 8

Result:

Thus the Breadth First Search was successfully executed

AIM:

Write a Program to Implement Breadth First Search.

Procedure:

Create a graph with key – value pair.

Assign empty list as visited nodes.

Initialize a queue as queue.


4
Define the sub program as bfs and passing parameter as visited, graph and
node.

Append the node in to visited and queue.

Creating loop to visit each node in Breadth First Search method.

Print the node which is visited in BFS method.

PROGRAM

Graph = {

‘5’: [‘3’, ‘7’],

‘3’: [‘2’, ‘4’],

‘7’: [‘8’],

‘2’: [],

‘4’: [‘8’],

‘8’: []

Visited = [] # List for visited nodes

Queue = [] # Initialize a queue.

Def bfs(visited, graph, node):

Visited.append(node)

Queue.append(node)

While queue: # Creating loop to visit each node

M = queue.pop(0)

Print(m, end=” “)
5
For neighbour in graph[m]:

If neighbour not in visited:

Visited.append(neighbour)

Queue.append(neighbour)

# Driver Code

Print(“Following is the Breadth-First Search”)

Bfs(visited, graph, ‘5’) # function calling

OUTPUT

Following is the Breadth-First Search 5 3 7 2 4 8

Result:

Thus the Breadth First Search was successfully executed

6
EX.NO 1.b Implementation of Uninformed search algorithms (DFS)

AIM:

Write a Program to Implement Depth First Search.

Procedure:

Create a graph with key – value pair.


Assign empty list as visited nodes.
Initialize a queue as queue.
Define the sub program as bfs and passing parameter as visited, graph and
node.
Append the node in to visited and queue.
Creating loop to visit each node in Breadth First Search method.
Print the node which is visited in BFS method.

PROGRAM

Graph = {
‘5’: [‘3’, ‘7’],
‘3’: [‘2’, ‘4’],
‘7’: [‘8’],
‘2’: [],
‘4’: [‘8’],
‘8’: []
}
Visited = [] # List for visited nodes.
Queue = [] # Initialize a queue.
Def bfs(visited, graph, node):
Visited.append(node)
Queue.append(node)
While queue: # Creating loop to visit each node
M = queue.pop(0)
Print(m, end=” “)
For neighbour in graph[m]:
If neighbour not in visited:
Visited.append(neighbour)
Queue.append(neighbour)
# Driver Code
7
Print(“Following is the Breadth-First Search”)
Bfs(visited, graph, ‘5’) # function calling

OUTPUT

Following is the Breadth-First Search 5 3 7 2 4 8

Result:

Thus the Breadth First Search was successfully executed.

8
EX.NO 2 Implementation of Informed search algorithms
(A* Algorithm)

Aim:
Write a program to implement A* Algorithm.

Program:

Def aStarAlgo(start_node, stop_node):


Open_set = set(start_node)
Closed_set = set()
G = {} #store distance from starting node
Parents = {} # parents contains an adjacency map of all nodes
#distance of starting node from itself is zero
G[start_node] = 0
#start_node is root node i.e it has no parent nodes
#so start_node is set to its own parent node
Parents[start_node] = start_node
While len(open_set) > 0:
N = None
#node with lowest f() is found
For v in open_set:
If n == None or g[v] + heuristic(v) < g[n] + heuristic(n):
N=v
If n == stop_node or Graph_nodes[n] == None:
Pass
Else:
For (m, weight) in get_neighbors(n):
#nodes ‘m’ not in first and last set are added to first
#n is set its parent
If m not in open_set and m not in closed_set:
Open_set.add(m)
Parents[m] = n
G[m] = g[n] + weight
#for each node m,compare its distance from start i.e g(m) to the
#from start through n node
Else:
If g[m] > g[n] + weight:
#update g(m)
G[m] = g[n] + weight
#change parent of m to n
Parents[m] = n
9
#if m in closed set,remove and add to open
If m in closed_set:
Closed_set.remove(m)
Open_set.add(m)
If n == None:
Print(‘Path does not exist!’)
Return None
# if the current node is the stop_node
# then we begin reconstructin the path from it to the start_node
If n == stop_node:
Path = []
While parents[n] != n:
Path.append(n)
N = parents[n]
Path.append(start_node)
Path.reverse()
Print(‘Path found: {}’.format(path))
Return path
# remove n from the open_list, and add it to closed_list
# because all of his neighbors were inspected
Open_set.remove(n)
Closed_set.add(n)
Print(‘Path does not exist!’)
Return None
#define fuction to return neighbor and its distance
#from the passed node
Def get_neighbors(v):
If v in Graph_nodes:
Return Graph_nodes[v]
Else:
Return None
Def heuristic(n):
H_dist = {
‘A’: 11,
‘B’: 6,
‘C’: 5,
‘D’: 7,
‘E’: 3,
‘F’: 6,
‘G’: 5,
‘H’: 3,
‘I’: 1,
‘J’: 0
}
10
Return H_dist[n]
#Describe your graph here
Graph_nodes = {
‘A’: [(‘B’, 6), (‘F’, 3)],
‘B’: [(‘A’, 6), (‘C’, 3), (‘D’, 2)],
‘C’: [(‘B’, 3), (‘D’, 1), (‘E’, 5)],
‘D’: [(‘B’, 2), (‘C’, 1), (‘E’, 8)],
‘E’: [(‘C’, 5), (‘D’, 8), (‘I’, 5), (‘J’, 5)],
‘F’: [(‘A’, 3), (‘G’, 1), (‘H’, 7)],
‘G’: [(‘F’, 1), (‘I’, 3)],
‘H’: [(‘F’, 7), (‘I’, 2)],
‘I’: [(‘E’, 5), (‘G’, 3), (‘H’, 2), (‘J’, 3)],
}
aStarAlgo(‘A’, ‘J’)

OUTPUT

Path found: [‘A’, ‘F’, ‘G’, ‘I’, ‘J’]

Result:

Thus the A* Algorithm was successfully executed.

11
EX.NO 3 Implementation of Informed search algorithms
(Hill Climbing Algorithm)

Aim:

Write a program to implement Hill Climbing Algorithm

Program:

Import random
Def randomSolution(tsp):
Cities = list(range(len(tsp)))
Solution = []
For I in range(len(tsp)):
randomCity = cities[random.randint(0, len(cities) – 1)]
solution.append(randomCity)
cities.remove(randomCity)
return solution
def routeLength(tsp, solution):
routeLength = 0
for I in range(len(solution)):
routeLength += tsp[solution[I – 1]][solution[i]]
return routeLength
def getNeighbours(solution):
neighbours = []
for I in range(len(solution)):
for j in range(I + 1, len(solution)):
neighbour = solution.copy()
neighbour[i] = solution[j]
neighbour[j] = solution[i]
neighbours.append(neighbour)
return neighbours
def getBestNeighbour(tsp, neighbours):
bestRouteLength = routeLength(tsp, neighbours[0])
bestNeighbour = neighbours[0]
for neighbour in neighbours:
currentRouteLength = routeLength(tsp, neighbour)
if currentRouteLength < bestRouteLength:
bestRouteLength = currentRouteLength
bestNeighbour = neighbour
return bestNeighbour, bestRouteLength
12
def hillClimbing(tsp):
currentSolution = randomSolution(tsp)
currentRouteLength = routeLength(tsp, currentSolution)
neighbours = getNeighbours(currentSolution)
bestNeighbour, bestNeighbourRouteLength = getBestNeighbour(tsp,
neighbours)
while bestNeighbourRouteLength < currentRouteLength:
currentSolution = bestNeighbour
currentRouteLength = bestNeighbourRouteLength
neighbours = getNeighbours(currentSolution)
bestNeighbour, bestNeighbourRouteLength = getBestNeighbour(tsp,
neighbours)
return currentSolution, currentRouteLength
tsp = [
[0, 400, 500, 300],
[400, 0, 300, 500],
[500, 300, 0, 400],
[300, 500, 400, 0]
]
Print(hillClimbing(tsp))

OUTPUT

([1, 0, 3, 2], 1400)

Result:

Thus the Hill Climbing Algorithm was successfully executed.

We'll implement a singly linked list with the following operations:

1. Initialize the list


2. Add an element at the end
3. Insert an element at a given position
4. Remove an element from a given position
5. Get an element at a given position
6. Set an element at a given position
7. Check if the list is empty
8. Get the size of the list
9. Print the list elements

Algorithm

13
1. Initialize the list:
o Create a linked list with a head node set to None.
2. Add an element at the end:
o Traverse to the end of the list and add a new node.
3. Insert an element at a given position:
o Traverse to the given position and insert a new node.
4. Remove an element from a given position:
o Traverse to the given position and remove the node.
5. Get an element at a given position:
o Traverse to the given position and return the node's value.
6. Set an element at a given position:
o Traverse to the given position and set the node's value.
7. Check if the list is empty:
o Return True if the head is None, False otherwise.
8. Get the size of the list:
o Traverse the list and count the nodes.
9. Print the list elements:
o Traverse the list and print each node's value.

Program:

class Node:
def init (self, data=None):
self.data = data

14
self.next = None

class LinkedList:
def init (self):
self.head = None

def add(self, data):


new_node = Node(data)
if self.head is None:
self.head = new_node
else:
current = self.head
while current.next:
current = current.next
current.next = new_node

def insert(self, index, data):


if index < 0:
raise IndexError("Index out of bounds")
new_node = Node(data)
if index == 0:
new_node.next =
self.head self.head =
new_node
else:
current = self.head
for _ in range(index - 1):
if current is None:
raise IndexError("Index out of bounds")
current = current.next
new_node.next = current.next
current.next = new_node

def remove(self, index):


if index < 0 or self.head is None:
raise IndexError("Index out of bounds")
if index == 0:
removed_data = self.head.data
self.head = self.head.next
return removed_data
current = self.head
for _ in range(index - 1):
if current.next is None:
raise IndexError("Index out of bounds")
15
current = current.next
if current.next is None:
raise IndexError("Index out of bounds")
removed_data = current.next.data
current.next = current.next.next
return removed_data

def get(self, index):


if index < 0:
raise IndexError("Index out of bounds")
current = self.head
for _ in range(index):
if current is None:
raise IndexError("Index out of bounds")
current = current.next
if current is None:
raise IndexError("Index out of bounds")
return current.data

def set(self, index, data):


if index < 0:
raise IndexError("Index out of bounds")
current = self.head
for _ in range(index):
if current is None:
raise IndexError("Index out of bounds")
current = current.next
if current is None:
raise IndexError("Index out of bounds")
current.data = data

def is_empty(self):
return self.head is None

def size(self):
count = 0
current = self.head
while current:
count += 1
current = current.next
return count

def print_list(self):

16
current = self.head
while current:
print(current.data, end=' -> ')
current = current.next
print('None')

# Testing the LinkedList


linked_list = LinkedList()
print("Is the list empty?", linked_list.is_empty()) # True
linked_list.add(10)
linked_list.add(20)
linked_list.add(30)
linked_list.print_list() # 10 -> 20 -> 30 -> None
linked_list.insert(1, 15)
linked_list.print_list() # 10 -> 15 -> 20 -> 30 -> None
print("Removed element:", linked_list.remove(2)) # 20
linked_list.print_list() # 10 -> 15 -> 30 -> None
print("Element at index 1:", linked_list.get(1)) # 15
linked_list.set(1, 25)
linked_list.print_list() # 10 -> 25 -> 30 -> None
print("Size of the list:", linked_list.size()) # 3
print("Is the list empty?", linked_list.is_empty()) # False

Output:

>>> %Run -c $EDITOR_CONTENT


Is the list empty? True
10 -> 20 -> 30 -> None
10 -> 15 -> 20 -> 30 -> None
Removed element: 20
10 -> 15 -> 30 -> None
Element at index 1: 15
10 -> 25 -> 30 -> None
Size of the list: 3
Is the list empty? False
>>>

Result:

Thus the program was created and the output is verified successfully.

17
EX.NO 5 A Implementation of Queue ADTs

Queue Operations

1. Initialize the queue


2. Enqueue (add an element to the rear)
3. Dequeue (remove an element from the front)
4. Peek (get the front element without removing it)
5. Check if the queue is empty
6. Get the size of the queue
7. Print the queue elements

5A.Implementation Using Python

List Algorithm

1. Initialize the queue:


o Create an empty list.
2. Enqueue (add an element to the rear):
o Append the element to the end of the list.
3. Dequeue (remove an element from the front):
o Remove and return the first element of the list.
4. Peek (get the front element without removing it):
o Return the first element of the list without removing it.
5. Check if the queue is empty:
o Return True if the list is empty, False otherwise.
6. Get the size of the queue:
o Return the length of the list using the len function.
7. Print the queue elements:
o Print all elements in the list

Program:

class Queue:
def init (self):
self.items = []
def enqueue(self, item):
self.items.append(item)
def dequeue(self):
if self.is_empty():
raise IndexError("Dequeue from an empty queue")

18
return
self.items.pop(0) def
peek(self):
if self.is_empty():
raise IndexError("Peek from an empty queue")
return self.items[0]
def is_empty(self):
return len(self.items) == 0

def size(self):
return len(self.items)

def print_queue(self):
for item in self.items:
print(item, end=' ')
print()

# Testing the Queue


queue = Queue()
print("Is the queue empty?", queue.is_empty()) # True
queue.enqueue(10)
queue.enqueue(20)
queue.enqueue(30)
queue.print_queue() # 10 20 30
print("Front element:", queue.peek()) # 10
print("Removed element:", queue.dequeue()) # 10
queue.print_queue() # 20 30
print("Size of the queue:", queue.size()) # 2
print("Is the queue empty?", queue.is_empty()) # False

Output

>>> %Run -c $EDITOR_CONTENT


Is the queue empty? True
10 20 30
Front element: 10
Removed element: 10
20 30
Size of the queue: 2
Is the queue empty? False
>>>

Result:
Thus the program was created and the output is verified successfully.
19
EX.NO 5B Implementation Using Linked List

Algorithm

1. Initialize the queue:


o Create a linked list with a head and tail node set to None.
2. Enqueue (add an element to the rear):
o Add a new node at the end of the linked list.
3. Dequeue (remove an element from the front):
o Remove and return the node at the front of the linked list.
4. Peek (get the front element without removing it):
o Return the value of the node at the front of the linked list
without removing it.
5. Check if the queue is empty:
o Return True if the head is None, False otherwise.
6. Get the size of the queue:
o Traverse the linked list and count the nodes.
7. Print the queue elements:
o Traverse the linked list and print each node's value.

Program:

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

class LinkedQueue:
def init (self):
self.head = None
self.tail = None
self._size = 0

def enqueue(self, data):


new_node = Node(data)
if self.tail:
self.tail.next =
new_node self.tail =
new_node
20
if not self.head:
self.head =
new_node
self._size += 1

def dequeue(self):
if self.is_empty():
raise IndexError("Dequeue from an empty queue")
removed_data = self.head.data
self.head = self.head.next
if not self.head:
self.tail = None
self._size -= 1
return removed_data

def peek(self):
if self.is_empty():
raise IndexError("Peek from an empty queue")
return self.head.data

def is_empty(self):
return self.head is None

def size(self):
return
self._size

def
print_queue(self):
current = self.head
while current:
print(current.data, end='
') current = current.next
print()

# Testing the LinkedQueue


linked_queue = LinkedQueue()
print("Is the queue empty?", linked_queue.is_empty()) # True
linked_queue.enqueue(10)
linked_queue.enqueue(20)
linked_queue.enqueue(30)
linked_queue.print_queue() # 10 20 30
print("Front element:", linked_queue.peek()) # 10
print("Removed element:", linked_queue.dequeue()) # 10
21
linked_queue.print_queue() # 20 30
print("Size of the queue:", linked_queue.size()) # 2

22
print("Is the queue empty?", linked_queue.is_empty()) # False

Output:

>>> %Run -c $EDITOR_CONTENT


Is the queue empty? True
10 20 30
Front element: 10
Removed element: 10
20 30
Size of the queue: 2
Is the queue empty? False
>>>

Result:

Thus the program was created and the output is verified successfully.

23
EX.NO 6 Applications of List, Stack and Queue ADTs

List ADT Applications

1. Polynomial Addition,subtraction
2. Dynamic Arrays
o Description: Dynamic arrays can resize themselves when
elements are added or removed.
o Example: Python lists, Java ArrayList.
3. Music Playlists
o Description: Store and manage a list of songs. Users can
add, remove, and rearrange songs.
o Example: Spotify playlists, iTunes playlists.
4. Contact Management
o Description: Store and manage contacts in a list format where
each contact can be edited, added, or removed.
o Example: Phone contact list, address book.
5. Shopping Cart
o Description: Items in an online shopping cart are stored in a
list, allowing users to add, remove, or modify items.
o Example: E-commerce websites like Amazon, eBay.

Stack ADT Applications

1. Expression Evaluation
o Description: Used to evaluate arithmetic expressions, especially
in converting infix to postfix expressions.
o Example: Calculators, compilers.
2. Undo Mechanism
o Description: Track user actions to allow undo operations in
applications like text editors.
o Example: Ctrl+Z in word processors, Photoshop history panel.
3. Function Call Management
o Description: Used by the operating system to manage
function calls and return addresses.
o Example: Call stack in programming languages.
4. Balanced Parentheses Checking
o Description: Check if an expression has balanced
parentheses using a stack.
o Example: Compiler syntax checking.

24
Queue ADT Applications

1. Print Queue
o Description: Manage print jobs sent to a printer, where jobs
are processed in the order they are received.
o Example: Office printers, network printers.
2. CPU Scheduling
o Description: Manage processes in an operating system,
where processes are scheduled based on their arrival order.
o Example: Round-robin scheduling, FCFS (First Come First
Serve) scheduling.
3. Customer Service Systems
o Description: Manage customers in a service center,
where customers are served in the order they arrive.
o Example: Bank teller systems, help desk support.

6A. List ADT Application: Polynomial Representation and Addition


Algorithm

1. Define a polynomial term as a tuple (coefficient, exponent).


2. Store a polynomial as a list of terms.
3. For polynomial addition:
o Initialize an empty list to store the result.
o Traverse both polynomials, adding coefficients of terms with
the same exponent.
o Append remaining terms from both polynomials to the result.

Program
class Polynomial:
def init (self):
self.terms = []

def add_term(self, coefficient, exponent):


self.terms.append((coefficient,
exponent))

def add(self, other):


result = Polynomial()
i, j = 0, 0
while i < len(self.terms) and j < len(other.terms):
term1 = self.terms[i]
25
term2 = other.terms[j]
if term1[1] == term2[1]:
result.add_term(term1[0] + term2[0],
term1[1])
i += 1
j += 1
elif term1[1] > term2[1]:
result.add_term(term1[0], term1[1])
i += 1
else:
result.add_term(term2[0], term2[1])
j += 1
while i < len(self.terms):
term = self.terms[i]
result.add_term(term[0], term[1])
i += 1
while j < len(other.terms):
term = other.terms[j]
result.add_term(term[0], term[1])
j += 1
return result

def str (self):


return " + ".join(f"{coef}x^{exp}" for coef, exp in self.terms)

# Testing the Polynomial class


poly1 = Polynomial()
poly1.add_term(3, 2)
poly1.add_term(5, 1)
poly2 = Polynomial()
poly2.add_term(4, 2)
poly2.add_term(2, 1)
poly2.add_term(1, 0)
result = poly1.add(poly2)
print("Polynomial 1:", poly1)
print("Polynomial 2:", poly2)
print("Sum:", result)

Output:
>>> %Run -c $EDITOR_CONTENT
Polynomial 1: 3x^2 + 5x^1
Polynomial 2: 4x^2 + 2x^1 + 1x^0
Sum: 7x^2 + 7x^1 + 1x^0
>>>
26
Result:
Thus the program was created and the output is verified successfully.

27
EX.NO 6 B Stack ADT Application: Balanced Parentheses Checker

Algorithm

1. Initialize an empty stack.


2. Traverse the string:
o If an opening bracket is encountered, push it onto the stack.
o If a closing bracket is encountered, check if the stack is empty
or the top of the stack is not the matching opening bracket.
o If not matching, return False.
o Otherwise, pop the stack.
3. After traversal, if the stack is empty, return True, else False.

Program
class Stack:
def init (self):
self.items = []

def push(self, item):


self.items.append(item)

def pop(self):
if self.is_empty():
raise IndexError("Pop from an empty stack")
return self.items.pop()

def peek(self):
if self.is_empty():
raise IndexError("Peek from an empty stack")
return self.items[-1]

def is_empty(self):
return len(self.items) == 0

def is_balanced_parentheses(expression):
stack = Stack()
opening = "({["
closing = ")}]"
matching = {')': '(', '}': '{', ']': '['}

28
for char in expression:
if char in opening:
stack.push(char)
elif char in closing:
if stack.is_empty() or stack.pop() != matching[char]:
return False
return stack.is_empty()

# Testing the is_balanced_parentheses function


expression1 = "{[()]}"
expression2 = "{[(])}"
print(f"Is '{expression1}' balanced? {is_balanced_parentheses(expression1)}")
# True
print(f"Is '{expression2}' balanced? {is_balanced_parentheses(expression2)}")
# False

Output:

>>> %Run -c $EDITOR_CONTENT


Is '{[()]}' balanced? True
Is '{[(])}' balanced? False
>>>

Result:

Thus the program was created and the output is verified successfully.

29
EX.NO 6 C Queue ADT Application: Printer Job Scheduling

Algorithm

1. Initialize an empty queue.


2. For adding a print job:
o Enqueue the job to the queue.
3. For processing a print job:
o Dequeue the job from the queue and process it.
4. Continue processing until the queue is empty.

Program
class Queue:
def init (self):
self.items = []

def enqueue(self, item):


self.items.append(item)

def dequeue(self):
if self.is_empty():
raise IndexError("Dequeue from an empty queue")
return self.items.pop(0)

def peek(self):
if self.is_empty():
raise IndexError("Peek from an empty queue")
return self.items[0]

def is_empty(self):
return len(self.items) == 0

def size(self):
return len(self.items)

def print_queue(self):
for item in self.items:
print(item, end=' ')
print()

class PrinterQueue:

30
def init (self):
self.queue =
Queue()

def add_job(self, job):


self.queue.enqueue(job)
print(f"Job '{job}' added to the queue.")

def process_job(self):
if self.queue.is_empty():
print("No jobs to process.")
else:
job = self.queue.dequeue()
print(f"Processing job: {job}")

# Testing the PrinterQueue


printer_queue = PrinterQueue()
printer_queue.add_job("Job1")
printer_queue.add_job("Job2")
printer_queue.add_job("Job3")
printer_queue.process_job() # Processing Job1
printer_queue.process_job() # Processing Job2
printer_queue.process_job() # Processing Job3
printer_queue.process_job() # No jobs to process.

Output:

>>> %Run -c $EDITOR_CONTENT


Job 'Job1' added to the queue.
Job 'Job2' added to the queue.
Job 'Job3' added to the queue.
Processing job: Job1
Processing job: Job2
Processing job: Job3
No jobs to process.
>>>

Result:

Thus the program was created and the output is verified successfully.

31
EX.NO 7 Implement recursive algorithms in Python

AIM:

To implement the linear search program using python.

ALGORITHM:

Step 1: Start
Step 2: Call Sequential _Search() with list of arguments.
Step 3:Assign pos=0
Step 4: Assign found=False
Step 5: Repeat step 5 to 7 until pos<len (dlist) occur false
Step 6: Check if dlist[pos]==item then go to step 6 otherwise goto step 7.
Step 7: Assign found = True
Step 8: Calculate pos =pos + 1
Step 9: Return and print found ,pos to Sequential_Search.
Step10: Stop.
Program
list_of_elements = [4, 3, 8, 9, 2, 7]
x=int (input ("Enter no tosearch :"))
found = False
for i in range (len(list_of_elements)):
if (list_of_elements[i] ==x):
found = True
print ("%d found at position %d"%( x,i))
break
if (found == False):
print ("%d is not in list"%x)
OUTPUT:
Enter no to search:4
4 found at position 0

32
RESULT: Thus the python program for the implementation of linear search was executed
and the output was obtained.

33
EX.NO 7 B Implement the Binary search Program

AIM:

To implement the binary search program using python.

ALGORITHM:
STEP 1: Start
STEP 2: Call binary_search() with list of arguments.
STEP 3:Assign first=0.
STEP 4: Calculate last = len(item_list)-1
STEP 5: Assignfound =False
STEP 6: Repeat step 7 to 12 until first <=last and not to foundoccur false.
STEP 7: Calculate mid = (first + last)/ / 2
STEP 8: Check if item_list[mid]==item then go to step 9otherwise go to step 10.
STEP 9: Assign found=True
STEP 10: Check if then < item_list[mid]then go to step 11otherwise go to step 12.
STEP 11: Calculate last=mid – 1
STEP 12: Calculate first=mid + 1
STEP 13: Repeat found to binary_search() and print the value
STEP 14: Repeat the step 2 to 13 for binary_search()STEP 15: Repeat the step 2 to 13 for
binary_search()
STEP16: Stop.
PROGRAM: BINARY SEARCH
def binary_search(item_list,item):
first = 0
last = len(item_list)-1
found = False
while( first<=last and not found):
mid = (first + last)//2
if item_list[mid] == item :

34
found = True
else:
if item < item_list[mid]:
last = mid - 1
else:
first = mid + 1
return found
print(binary_search([1,82,3,5,8], 9))
print(binary_search([1,2,3,5,8], 5))

Output:
False
True

RESULT:
Thus the python program for the implementation of binary search was executed and output
was obtained.

35
EX.NO 7 C Bubble Sort

AIM:

To sort the elements using bubble sort.

ALGORITHM:
STEP 1: Start
STEP 2: Call bubbleSort function with list of arguments.
STEP 3:specify the for loop in range(0,len(A)-1)
STEP 4: specify the for loop in range(len(A)-1)
Step 5: Swap two numbers.
Step 6: Print the result.
Program
def bubbleSort(A):
for n in range(0,len(A)-1):
for i in range(len(A)-1):
if A[i]>A[i+1]:
temp = A[i]
A[i]=A[i+1]
A[i+1]=temp
A=[56,91,35,75,48]
bubbleSort(A)
print(A)

Output:
[35, 48, 56, 75, 91]

RESULT:
Thus the python program for the implementation of bubble sort was executed and output was
obtained.

36
EX.NO 7 D Insertion Sort

AIM:

To sort the elements using Insertion sort.

ALGORITHM:
STEP 1: Start
STEP 2: Call insertionSort function with list of arguments.
STEP 3:specify the for loop in range(1,len(A))
STEP 4: specify the while loop with condition k>0 and temp <A[k-1]
Step 5: Swap two numbers.
Step 6: Print the result.

Program:
def insertionsort(A):
for i in range(1,len(A)):
temp=A[i]
k=i
while k>0 and temp <A[k-1]:
A[k]=A[k-1]
k=k-1
A[k]=temp

A=[9,7,6,15,5,10,11]
insertionsort(A)
print(A)
Output:
[5, 6, 7, 9, 10, 11, 15]
RESULT:Thus the python program for the implementation of insertion sort was executed
and output was obtained.

37
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.

Program:

hashTable = [[],] * 10
def checkPrime(n):
if n == 1 or n == 0:
return 0
for i in range(2, n//2):
if n % i == 0:
return 0
return 1
def getPrime(n):
if n % 2 == 0:
n=n+1
while not checkPrime(n):
n += 2
return n
def hashFunction(key):
capacity = getPrime(10)
return key % capacity
def insertData(key, data):

38
index = hashFunction(key)
hashTable[index] = [key, data]
def removeData(key):
index = hashFunction(key)
hashTable[index] = 0
insertData(123, "apple")
insertData(432, "mango")
insertData(213, "banana")
insertData(654, "guava")
print(hashTable)
removeData(123)
print(hashTable)

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

Result:
Thus the python program for the implementation of hash function was executed and output
was obtained.

39
EX.NO 9 Tree representation and traversal algorithms

Aim: To implement the tree representation and Traversal algorithm in python.

In-order Traversal

Procedure:
Until all nodes of the tree are not visited
1. Step 1 - Traverse the left subtree recursively.
2. Step 2 - Visit the root node.
3. Step 3 - Traverse the right subtree recursively.

Program:

class Node:
def init (self, data):

self.left = None
self.right = None
self.data = data
# Insert Node
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

# Print the Tree

40
41
def PrintTree(self):
if self.left:
self.left.PrintTree()
print( self.data),
if self.right:
self.right.PrintTree()

# Inorder traversal
# Left -> Root -> Right
def inorderTraversal(self, root):
res = []
if root:
res = self.inorderTraversal(root.left)
res.append(root.data)
res = res + self.inorderTraversal(root.right)
return res

root = Node(27)
root.insert(14)
root.insert(35)
root.insert(10)
root.insert(19)
root.insert(31)
root.insert(42)
print(root.inorderTraversal(root))

Output
[10, 14, 19, 27, 31, 35, 42]

Pre-order Traversal
Procedure:
Until all nodes of the tree are not visited
1. Step 1 - Visit the root node
2. Step 2 - Traverse the left subtree recursively.
3. Step 3 - Traverse the right subtree recursively.

42
Program:

class Node:
def init (self, data):
self.left = None
self.right = None
self.data = data
# Insert Node
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

# Print the Tree


def PrintTree(self):
if self.left:
self.left.PrintTree()
print( self.data),
if self.right:
self.right.PrintTree()

# Preorder traversal
# Root -> Left ->Right
def PreorderTraversal(self, root):
res = []
if root:
res.append(root.data)
res = res + self.PreorderTraversal(root.left)

43
res = res + self.PreorderTraversal(root.right)
return res

root = Node(27)
root.insert(14)
root.insert(35)
root.insert(10)
root.insert(19)
root.insert(31)
root.insert(42)
print(root.PreorderTraversal(root))

Output
[27, 14, 10, 19, 35, 31, 42]

Post-order Traversal
Procedure:
Until all nodes of the tree are not visited

1. Step 1 - Traverse the left subtree recursively.


2. Step 2 - Traverse the right subtree recursively.
3. Step 3 - Visit the root node.

class Node:

def init (self, data):

self.left = None
self.right = None
self.data = data
# Insert Node
def insert(self, data):

if self.data:
if data < self.data:
if self.left is None:
self.left = Node(data)
else:

44
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

# Print the Tree


def PrintTree(self):
if self.left:
self.left.PrintTree()
print( self.data),
if self.right:
self.right.PrintTree()

# Postorder traversal
# Left ->Right -> Root
def PostorderTraversal(self, root):
res = []
if root:
res = self.PostorderTraversal(root.left)
res = res + self.PostorderTraversal(root.right)
res.append(root.data)
return res

root = Node(27)
root.insert(14)
root.insert(35)
root.insert(10)
root.insert(19)
root.insert(31)
root.insert(42)
print(root.PostorderTraversal(root))

Output
[10, 19, 14, 31, 42, 35, 27]

45
Result:
Thus the python program for the Tree traversal was created and the output is
verified successfully.

46
EX.NO 10 Implementation of Binary search Tree

Aim:
To write the Binary search tree for insertion , searching and deletion operation
using python
Program:
class TreeNode:
def init (self, key):
self.left = None
self.right = None
self.val = key
class BinarySearchTree:
def init (self):
self.root = None
def insert(self,
key):
if self.root is None:
self.root = TreeNode(key)
else:
self._insert_rec(self.root,
key) def _insert_rec(self, node,
key):
if key < node.val:
if node.left is None:
node.left =
TreeNode(key)
else:

47
self._insert_rec(node.left, key)
else:
if node.right is None:

48
node.right = TreeNode(key)
else:
self._insert_rec(node.right,
key) def search(self, key):
return self._search_rec(self.root, key)
def _search_rec(self, node, key):
if node is None or node.val == key:
return node
if key < node.val:
return self._search_rec(node.left, key)
return self._search_rec(node.right, key)
def delete(self, key):
self.root = self._delete_rec(self.root, key)
def _delete_rec(self, node, key):
if node is None:
return node

if key < node.val:


node.left = self._delete_rec(node.left, key)
elif key > node.val:
node.right = self._delete_rec(node.right, key)
else:
if node.left is None:
return node.right
elif node.right is None:
return node.left
temp = self._min_value_node(node.right)

49
node.val = temp.val
node.right = self._delete_rec(node.right, temp.val)

return node
def _min_value_node(self, node):
current = node
while current.left is not None:
current = current.left
return current
def inorder(self):
return
self._inorder_rec(self.root) def
_inorder_rec(self, node):
return self._inorder_rec(node.left) + [node.val] +
self._inorder_rec(node.right) if node else []
# Example usage
bst = BinarySearchTree()
# Inserting values
values_to_insert = [50, 30, 70, 20, 40, 60, 80]
for value in values_to_insert:
bst.insert(value)
# Inorder traversal
inorder_result = bst.inorder()
print("Inorder traversal:", inorder_result)
# Searching for a value
search_value = 60
found_node = bst.search(search_value)
if found_node:

50
print(f"Found: {found_node.val} The value is present") # Output: Found: 60

51
else:
print("Not found")

# Deleting a value
bst.delete(20)
print("Inorder traversal after deleting 20:", bst.inorder())
# Deleting another value
bst.delete(30)
print("Inorder traversal after deleting 30:", bst.inorder())
# Deleting a leaf node
bst.delete(70)
print("Inorder traversal after deleting 70:", bst.inorder())

Output

Inorder traversal: [20, 30, 40, 50, 60, 70, 80]


Found: 60 The value is present
Inorder traversal after deleting 20: [30, 40, 50, 60, 70, 80]
Inorder traversal after deleting 30: [40, 50, 60, 70, 80]
Inorder traversal after deleting 70: [40, 50, 60, 80]

Result:
Thus the python program for Implementation of Binary search Tree was created
and the output is verified successfully

52
EX.NO 11 Implentation of Graph representation and Traversal
Algorithm.

Aim:
To write the Implentation of Graph representation and Traversal Algorithm
using python

Depth First Traversal

class graph:
def init (self,gdict=None):
if gdict is None:
gdict = {}
self.gdict = gdict
# Check for the visisted and unvisited nodes
def dfs(graph, start, visited = None):
if visited is None:
visited = set()
visited.add(start)
print(start)
for next in graph[start] - visited:
dfs(graph, next, visited)
return
visited gdict =
{
"a" : set(["b","c"]),
"b" : set(["a", "d"]),
"c" : set(["a", "d"]),
"d" : set(["e"]),
"e" : set(["a"])
}
53
54
dfs(gdict, 'a')
Output:
a
b
d
e
c
Breadth First Traversal

import
collections class
graph:
def init (self,gdict=None):
if gdict is None:
gdict = {}
self.gdict = gdict
def bfs(graph, startnode):
# Track the visited and unvisited nodes using queue
seen, queue = set([startnode]), collections.deque([startnode])
while queue:
vertex = queue.popleft()
marked(vertex)
for node in graph[vertex]:
if node not in seen:
seen.add(node)
queue.append(node)

def marked(n):

55
print(n)

56
# The graph dictionary
gdict = {
"a" : set(["b","c"]),
"b" : set(["a", "d"]),
"c" : set(["a", "d"]),
"d" : set(["e"]),
"e" : set(["a"])
}
bfs(gdict, "a")
Output:
a
c
b
d
e

Result:
Thus the python program for Graph Traversal was created and the output is
verified successfully

57
EX.NO 12 Implementation of Dijkstra’s shortest path algorithm

Aim:
To write the Implementation of Dijkstra’s shortest path algorithm using python
Program:
class Graph():
def init (self, vertices):
self.V = vertices
self.graph = [[0 for column in range(vertices)]
for row in range(vertices)]
def printSolution(self, dist):
print("Vertex \t Distance from
Source") for node in range(self.V):
print(node, "\t\t", dist[node])
# A utility function to find the vertex with
# minimum distance value, from the set of vertices
# not yet included in shortest path tree
def minDistance(self, dist, sptSet):
# Initialize minimum distance for next
node min = 1e7
# Search not nearest vertex not in the
# shortest path tree
for v in range(self.V):

58
if dist[v] < min and sptSet[v] == False:
min = dist[v]
min_index = v
return min_index
# Function that implements Dijkstra's single source
# shortest path algorithm for a graph represented
# using adjacency matrix representation
def dijkstra(self, src):

dist = [1e7] * self.V


dist[src] = 0
sptSet = [False] * self.V
for cout in
range(self.V):
# Pick the minimum distance vertex from
# the set of vertices not yet processed.
# u is always equal to src in first iteration
u = self.minDistance(dist, sptSet)
# Put the minimum distance vertex in the
# shortest path tree
sptSet[u] = True
# Update dist value of the adjacent
vertices # of the picked vertex only if the
current
# distance is greater than new distance
and # the vertex in not in the shortest path
tree for v in range(self.V):
if (self.graph[u][v] > 0
59
and sptSet[v] == False
and

60
dist[v] > dist[u] + self.graph[u][v]):
dist[v] = dist[u] + self.graph[u][v]
self.printSolution(dist)
# Driver program
g = Graph(9)
g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
[4, 0, 8, 0, 0, 0, 0, 11, 0],
[0, 8, 0, 7, 0, 4, 0, 0, 2],
[0, 0, 7, 0, 9, 14, 0, 0, 0],
[0, 0, 0, 9, 0, 10, 0, 0, 0],
[0, 0, 4, 14, 10, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 1, 6],
[8, 11, 0, 0, 0, 0, 1, 0, 7],
[0, 0, 2, 0, 0, 0, 6, 7, 0]
]
g.dijkstra(0)
Output:
Vertex Distance from Source
0 0
1 4
2 12
3 19
4 21
5 11
6 9
7 8
8 14

61
Result:
Thus the python program for Implementation of Dijkstra’s shortest path
algorithm was created and the output is verified successfully

62
EX.NO 13 A Implementation of minimum spanning tree algorithms

Aim:
To write the Implementation of minimum spanning tree algorithms using Prim’s
algorithm using python
Program:
def init (self, size):
self.adj_matrix = [[0] * size for _ in range(size)]
self.size = size
self.vertex_data = [''] * size

def add_edge(self, u, v, weight):


if 0 <= u < self.size and 0 <= v < self.size:
self.adj_matrix[u][v] = weight
self.adj_matrix[v][u] = weight # For undirected graph

def add_vertex_data(self, vertex, data):


if 0 <= vertex < self.size:
self.vertex_data[vertex] = data

def prims_algorithm(self):
in_mst = [False] * self.size
key_values = [float('inf')] * self.size
parents = [-1] * self.size

key_values[0] = 0 # Starting vertex

63
print("Edge \tWeight")
for _ in range(self.size):
u = min((v for v in range(self.size) if not in_mst[v]), key=lambda v:
key_values[v])

in_mst[u] = True

if parents[u] != -1: # Skip printing for the first vertex since it has no
parent

print(f"{self.vertex_data[parents[u]]}-{self.vertex_data[u]}
\t{self.adj_matrix[u][parents[u]]}")

for v in range(self.size):
if 0 < self.adj_matrix[u][v] < key_values[v] and not in_mst[v]:
key_values[v] = self.adj_matrix[u][v]
parents[v] = u

g = Graph(8)

g.add_vertex_data(0, 'A')
g.add_vertex_data(1, 'B')
g.add_vertex_data(2, 'C')
g.add_vertex_data(3, 'D')
g.add_vertex_data(4, 'E')
g.add_vertex_data(5, 'F')
g.add_vertex_data(6, 'G')
g.add_vertex_data(7, 'H')
g.add_edge(0, 1, 4) # A - B

64
g.add_edge(0, 3, 3) # A - D
g.add_edge(1, 2, 3) # B - C
g.add_edge(1, 3, 5) # B - D
g.add_edge(1, 4, 6) # B - E
g.add_edge(2, 4, 4) # C - E
g.add_edge(2, 7, 2) # C - H
g.add_edge(3, 4, 7) # D - E
g.add_edge(3, 5, 4) # D - F
g.add_edge(4, 5, 5) # E - F
g.add_edge(4, 6, 3) # E - G
g.add_edge(5, 6, 7) # F - G
g.add_edge(6, 7, 5) # G - H

print("Prim's Algorithm MST:")


g.prims_algorithm()
Output
Prim's Algorithm MST:
Edge Weight
A-D 3
A-B 4
B-C 3
C-H 2
C-E 4
E-G 3
D-F 4
Result:
Thus the python program for Implementation of Prim’s algorithm was created
and the output is verified successfully

65
EX.NO 13 B Implementation of minimum spanning tree algorithms

Aim:
To write the Implementation of minimum spanning tree algorithms using Kruskals
algorithm using python
Program:
class Graph:
def init (self, vertices):
self.V = vertices
self.graph = []

# Function to add an edge to graph


def addEdge(self, u, v, w):
self.graph.append([u, v, w])

# A utility function to find set of an element


i # (truly uses path compression technique)
def find(self, parent, i):
if parent[i] != i:

# Reassignment of node's parent


# to root node as
# path compression requires
parent[i] = self.find(parent, parent[i])
return parent[i]
# A function that does union of two sets of x and y
# (uses union by rank)
def union(self, parent, rank, x, y):

66
# Attach smaller rank tree under root of
# high rank tree (Union by Rank)
if rank[x] < rank[y]:
parent[x] = y
elif rank[x] > rank[y]:
parent[y] = x

# If ranks are same, then make one as root


# and increment its rank by one
else:
parent[y] = x
rank[x] += 1

# The main function to construct MST


# using Kruskal's algorithm
def KruskalMST(self):
# This will store the resultant MST
result = []
# An index variable, used for sorted
edges i = 0
# An index variable, used for
result[] e = 0
# Sort all the edges in
# non-decreasing order of their
# weight
self.graph = sorted(self.graph,
key=lambda item: item[2])

67
parent = []
rank = []
# Create V subsets with single elements
for node in range(self.V):
parent.append(node)
rank.append(0)
# Number of edges to be taken is less than to V-1
while e < self.V - 1:
# Pick the smallest edge and increment
# the index for next iteration
u, v, w = self.graph[i]
i=i+1
x = self.find(parent, u)
y = self.find(parent, v)
# If including this edge doesn't
# cause cycle, then include it in result
# and increment the index of result
# for next edge
if x != y:
e=e+1
result.append([u, v, w])
self.union(parent, rank, x, y)
# Else discard the edge
minimumCost = 0
print("Edges in the constructed MST")
for u, v, weight in result:
minimumCost += weight

68
print("%d -- %d == %d" % (u, v, weight))
print("Minimum Spanning Tree", minimumCost)
# Driver code
if name == ' main ':
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)
# Function call
g.KruskalMST()

Output:
>>> %Run -c $EDITOR_CONTENT
Edges in the constructed MST
2 -- 3 == 4
0 -- 3 == 5
0 -- 1 == 10
Minimum Spanning Tree 19
>>>

Result:
Thus the python program for Implementation of Prim’s algorithm was created
and the output is verified successfully

69

You might also like