Daa Lab Manual
Daa Lab Manual
LAB MANUAL
DESIGN AND ANALYSIS OF ALGORITHEMS(BUE401)
Prof.Ambika Shahbadkar
(Assistance Professor)
Department of computer science and engineering
DESIGN AND ANALYSIS OF ALGORITHEMS(BUEL404)
1. Sort a given set of n integer elements using Selection Sort method and compute its time
complexity. Run the program for varied values of n> 5000 and record the time taken to sort. Plot a
graph of the time taken versus n. The elements can be read from a file or can be generated using the
random number generator. Demonstrate using C/C++/Python how the brute force method works
along with its time complexity analysis: worst case, average case and best case.
import time
import random
import matplotlib.pyplot as plt
arr = input("Enter the list of elements separated by space: ").split()
arr = [int(x) for x in arr]
print("Input array: ", arr)
n = len(arr)
def selection_sort(arr):
for i in range(n):
min_idx = i
for j in range(i+1, n):
if arr[j]<arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
sorted_arr = selection_sort(arr)
print("Sorted array", sorted_arr)
# time taken to sort
start_time = time.time()
sorted_arr = selection_sort(arr)
end_time = time.time()
print("Time taken to sort", end_time - start_time, "seconds")
# For n>5000
n_values = [5000, 6000, 7000, 8000]
time_values = []
for n in n_values:
arr = [random.randint(1, 9) for _ in range(n)] # Generating random
start_time = time.time()
sorted_arr = selection_sort(arr)
end_time = time.time()
time_taken = end_time - start_time
print("Time taken to sort",n, "Elements:",time_taken, "seconds")
time_values.append(time_taken)
output
Enter the list of elements separated by space: 12 11 13 5 6 7
Input array: [12, 11, 13, 5, 6, 7]
Sorted array [5, 6, 7, 11, 12, 13]
Time taken to sort 0.0 seconds
Time taken to sort 5000 Elements: 0.2671678066253662 seconds
Time taken to sort 6000 Elements: 0.3778214454650879 seconds
Time taken to sort 7000 Elements: 0.5204188823699951 seconds
Time taken to sort 8000 Elements: 0.676368236541748 seconds
2. Sort a given set of n integer elements using Quick Sort method and compute its time
complexity. Run the program for varied values of n> 5000 and record the time taken to sort. Plot a
graph of the time taken versus n. The elements can be read from a file or can be generated using
the random number generator. Demonstrate using C/C++/Python how the divide-and-conquer
method works along with its time complexity analysis: worst case, average case, and best case.
import time
import random
import matplotlib.pyplot as plt
arr = input("enter the list of elements seperated by space: ").split()
arr = [int(x) for x in arr]
print("input array: ",arr)
def quick_sort(arr):
if len(arr)<=1:
return arr
# choose a last element as pivot
pivot = arr[len(arr)-1]
#initialize left and right array
left = []
right = []
# partitioning the array into left and right subarray
for i in range(len(arr)-1):
if arr[i]<pivot:
left.append(arr[i])
else:
right.append(arr[i])
return quick_sort(left)+[pivot]+quick_sort(right)
sorted_arr = quick_sort(arr)
print("sorted array: ",sorted_arr)
# measure time taken to sort
start_time = time.time()
sorted_arr = quick_sort(arr)
end_time = time.time()
print("time taken to sort : ",end_time - start_time, "seconds")
# for n>5000
n_values = [5000,6000,7000,8000]
time_values = []
for n in n_values:
arr = [random.randint(1,9) for _ in range(n)] # generate random array
start_time = time.time()
sorted_arr = quick_sort(arr)
end_time = time.time()
time_taken = end_time - start_time
print("time taken to sort", n, "elements:", end_time-start_time, "seconds")
time_values.append(time_taken)
output
enter the list of elements seperated by space: 12 11 13 5 6 7
input array: [12, 11, 13, 5, 6, 7]
sorted array: [5, 6, 7, 11, 12, 13]
time taken to sort : 0.0 seconds
time taken to sort 5000 elements: 0.0527496337890625 seconds
time taken to sort 6000 elements: 0.09432673454284668 seconds
time taken to sort 7000 elements: 0.11038565635681152 seconds
time taken to sort 8000 elements: 0.14146757125854492 seconds
3. Sort a given set of n integer elements using Merge Sort method and compute its time complexity.
Run the program for varied values of n> 5000, and record the time taken to sort. Plot a graph of the
time taken versus n. The elements can be read from a file or can be generated using the random
number generator. Demonstrate using C/C++/Python how the divide-and-conquer method works
along with its time complexity analysis: worst case, average case, and best case.
import time
import random
import matplotlib.pyplot as plt
arr = input("enter the list of elements seperated by space: ").split()
arr = [int(x) for x in arr]
print("input array: ",arr)
def merge_sort(arr):
if len(arr)<=1:
return arr
mid = len(arr)//2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left,right)
def merge(left,right):
result = []
i=j=0
# for n>5000
n_values = [5000,6000,7000,8000]
time_values = []
for n in n_values:
arr = [random.randint(1,9) for _ in range(n)] # generate random array
start_time = time.time()
sorted_arr = merge_sort(arr)
end_time = time.time()
time_taken = end_time - start_time
print("time taken to sort", n, "elements:", end_time-start_time, "seconds")
time_values.append(time_taken)
#plotting the graph
plt.plot(n_values,time_values,'purple')
plt.xlabel("number of elements ")
plt.ylabel("time taken in seconds")
plt.title(" time complexity analysis of merge sort")
plt.grid(True)
plt.show()
output
enter the list of elements seperated by space: 12 11 13 5 6 7
input array: [12, 11, 13, 5, 6, 7]
sorted array: [5, 6, 7, 11, 12, 13]
time taken to sort : 0.0 seconds
time taken to sort 5000 elements: 0.0 seconds
time taken to sort 6000 elements: 0.0 seconds
time taken to sort 7000 elements: 0.010013818740844727 seconds
time taken to sort 8000 elements: 0.0 seconds
n = 4 #Number of vertices
inf = float('inf')
graph = [[0,3,inf,7],
[8,0,2,inf],
[5,inf,0,1],
[2,inf,inf,0]]
def floyd_warshall(graph):
n = len(graph)
dist = []
for row in graph:
dist.append(row[:])
for k in range(n):
for j in range(n):
for i in range(n):
dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j])
return dist
shortest_paths = floyd_warshall(graph)
# printing Output:
print("shortest_paths between all pairs of vertices:")
for row in shortest_paths:
for dist in row:
if dist == inf:
print("inf",end = " ")
else:
print(dist,end = " ")
print()
output
shortest_paths between all pairs of vertices:
0356
5023
3601
2570
Or
# Input
n = int(input("Enter the number of vertices:"))
inf = float('inf')
print("enter the adjacency matrix separated by space")
# enter inf for infinity
graph = []
for i in range(n):
row = input().split()
graph.append([inf if x == 'inf' else int(x) for x in row])
def floyd_warshall(graph):
n = len(graph)
dist = []
for row in graph:
dist.append(row[:])
for k in range(n):
for j in range(n):
for i in range(n):
dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j])
return dist
shortest_paths = floyd_warshall(graph)
# printing Output:
print("shortest_paths between all pairs of vertices:")
for row in shortest_paths:
for dist in row:
if dist == inf:
print("inf",end = " ")
else:
print(dist,end = " ")
print()
output
Enter the number of vertices:4
enter the adjacency matrix separated by space
0 3 inf 7
8 0 2 inf
5 inf 0 1
2 inf inf 0
shortest_paths between all pairs of vertices:
0356
5023
3601
2570
self.memo[next_city][subset] = min_distance
self.__calculate_min_cost()
self.__find_shortest_path()
def __calculate_min_cost(self):
for i in range(self.total_cities):
if i == self.start_city:
continue
path_cost = self.memo[i][self.end_state]
if path_cost < self.min_path_cost:
self.min_path_cost = path_cost
def __find_shortest_path(self):
state = self.end_state
for i in range(1, self.total_cities):
best_index = -1
best_distance = float('inf')
for j in range(self.total_cities):
if j == self.start_city or self.__is_not_in_subset(j, state):
continue
new_distance = self.memo[j][state]
if new_distance <= best_distance:
best_index = j
best_distance = new_distance
self.shortest_path.append(best_index)
state = state ^ (1 << best_index)
self.shortest_path.append(self.start_city)
self.shortest_path.reverse()
def __initialize_memo(self):
for destination_city in range(self.total_cities):
if destination_city == self.start_city:
continue
distance_matrix = [
[0, 328, 259, 180, 314, 294, 269, 391],
[328, 0, 83, 279, 107, 131, 208, 136],
[259, 83, 0, 257, 70, 86, 172, 152],
[180, 279, 257, 0, 190, 169, 157, 273],
[314, 107, 70, 190, 0, 25, 108, 182],
[294, 131, 86, 169, 25, 0, 84, 158],
start_city = 0
tour = TravellingSalesmanProblem(distance_matrix, start_city)
tour.solve()
print("Shortest path :", tour.shortest_path)
print("Minimum path cost :", tour.min_path_cost)
output
Shortest path : [0, 3, 6, 5, 4, 2, 1, 7]
Minimum path cost : 735
5.Design and implement c/c++/python program to find a subst of given set ={S1,s2,…..Sn} of n
positive integer whose SUM is equal to a given positive integer d.For example ,if as={1,,2,5,6,8} and
d= 9,there are two solutions {1,2,6} and {1,8} Display a suitable message if the given problem
instance doesn’t have a solution.
# INPUT
S = input("eneter the elements of set S seperated by space: ").split()
S = [int(x) for x in S]
print("set S : ",S)
# target sum
d = int(input("enter the sum d: "))
# print("target sum d :",d)
def sum_of_subset(S,d):
result = []
def backtrack(start, current_subset, current_sum):
if current_sum == d:
result.append(list(current_subset))
return
if current_sum > d:
return
for i in range(start, len(S)):
current_subset.append(S[i])
backtrack(i + 1, current_subset, current_sum + S[i])
current_subset.pop()
backtrack(0, [], 0)
return result
subsets = sum_of_subset(S,d)
if subsets:
print("subsets whose sum is ",d, "are:")
for j in subsets:
print(j)
else:
print("no subset found with sum: ",d)
output
eneter the elements of set S seperated by space: 1 2 5 6 8
set S : [1, 2, 5, 6, 8]
enter the sum d: 9
subsets whose sum is 9 are:
[1, 2, 6]
[1, 8]
6.Design and implement c/c++/python program to find all Hamiltonian cycle in a connected
undirected Graph G of n vertices using Backtracking principle.
n = int(input("enter the number of vertices in the graph: "))
def find_hamiltonian_cycles(graph):
n =len(graph)
start_vertex = 0
result = []
#identifying cycles
def hamiltonian_cycle(path):
if len(path) == n and graph[path[-1]][path[0]] == 1:
result.append(path[:])
return
last_vertex = path[-1]
for v in range(n):
if v not in path and graph[last_vertex][v] == 1:
hamiltonian_cycle(path + [v])
hamiltonian_cycle([start_vertex])
return result
cycles = find_hamiltonian_cycles(graph)
if cycles:
print("hamiltonian cycles found:")
for cycle in cycles:
cycle_str = " -> ".join([str(vertex) for vertex in cycle])
print(cycle_str + " -> " + str(cycle[0]))
else:
print("no hamiltonian cycle found")
Output
enter the number of vertices in the graph: 5
enter the adjacency matrix where each row seperated by spaces:
0 1 0 1 0
1 0 0 1 0
0 1 0 0 1
1 1 0 0 1
1 1 1 1 0
Enter the source vertex: 1
hamiltonian cycles found: 0 -> 3 -> 4 -> 2 -> 1 -> 0
foriinrange(n+1):
forwinrange(capacity+1):
ifi==0orw==0:
K[i][w]=0
elifweight[i-1]<=w:
K[i][w]=max(profit[i-1]+K[i-1][w-weight[i-1]],K[i-1][w])
else:
K[i][w]=K[i-1][w]
returnK[n][capacity]
max_profit=DP_Knapsack(capacity,weight,profit,n)
print("maxprofitearned=",max_profit)
output
maxprofitearned=180
n=int(input("enterthenumberofitems:"))
print("entertheweightandprofitforeachitem:")
weight=[]
profit=[]
foriinrange(n):
w=int(input("weightofitem{}:".format(i+1)))
p=int(input("profitofitem{}:".format(i+1)))
weight.append(w)
profit.append(p)
capacity=int(input("entertyhecapacityoftheknapsack:"))
defDP_Knapsack(capacity,weight,profit,n):
k=[[0forxinrange(capacity+1)]forxinrange(n+1)]
foriinrange(n+1):
forwinrange(capacity+1):
ifi==0orw==0:
k[i][w]=0
elifweight[i-1]<=w:
k[i][w]=max(profit[i-1]+k[i-1][w-weight[i-1]],k[i-1][w])
else:
k[i][w]=k[i-1][w]
returnk[n][capacity]
max_profit=DP_Knapsack(capacity,weight,profit,n)
print("maxprofitearned=",max_profit)
Output
return total_profit
max_profit = greedy_Knapsack(capacity, weight, profit ,n)
print("max profit earned = ", max_profit)
n = int(input("enter the number of items:"))
print("enter the weight and profit for each item:")
weight = []
profit = []
for i in range(n):
w = int(input("weight of item {}:".format(i+1)))
p = int(input("profit of item {}:".format(i+1)))
weight.append(w)
profit.append(p)
def greedy_Knapsack(capacity, weight, profit, n):
ratio = [(profit[i]/weight[i],weight[i],profit[i]) for i in range(n)]
return total_profit
max_profit = greedy_Knapsack(capacity, weight, profit ,n)
print("max profit earned(Greedy Approach) = ", max_profit)
Output
8. From a given vertex in a weighted connected gragh ,find shortest paths to other vertices
using Dijkstra’s algorithem .Write the program in c/c++/python.
Output