You are on page 1of 32

Analysis & Design Of Algorithms

Practical 1
Aim: Implementation and Time analysis of sorting algorithms. Bubble sort,
Selection sort, Insertion sort, Merge sort and Quicksort.

Bubble sort:
def bubblesort(elements):

swapped = False

for n in range(len(elements)-1, 0, -1):

for i in range(n):

if elements[i] > elements[i + 1]:

swapped = True

elements[i], elements[i + 1] = elements[i + 1], elements[i] if not


swapped:

return

elements = [39, 12, 18, 85, 72, 10, 2, 18]

print("Unsorted list is,")

print(elements)

bubblesort(elements)

print("Sorted Array is, ")

print(elements)

Output:

Unsorted list is,


[39, 12, 18, 85, 72, 10, 2, 18]
Sorted Array is,
[2, 10, 12, 18, 18, 39, 72, 85]

1
Analysis & Design Of Algorithms

Selection sort:
def selectionSort(array, size):

for ind in range(size):

min_index = ind
for j in range(ind + 1, size):

if array[j] < array[min_index]:


min_index = j

(array[ind], array[min_index]) = (array[min_index], array[ind])

arr = [-2, 45, 0, 11, -9,88,-97,-202,747]


size = len(arr)
selectionSort(arr, size)
print('The array after sorting in Ascending Order by selection sort is:')
print(arr)

Output:
The array after sorting in Ascending Order by selection sort is:
[-202, -97, -9, -2, 0, 11, 45, 88, 747]

2
Analysis & Design Of Algorithms

Insertion sort:

def insertionSort(arr):

for i in range(1, len(arr)):

key = arr[i]

j = i-1

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

arr[j+1] = arr[j]

j -= 1

arr[j+1] = key

arr = [12, 11, 13, 5, 6]

insertionSort(arr)

lst = []
print("Sorted array is : ")

for i in range(len(arr)):

lst.append(arr[i])
print(lst)

Output:

Sorted array is:


[5, 6, 11, 12, 13]

3
Analysis & Design Of Algorithms

Merge sort:
def merge(arr, l, m, r):

n1 = m - l + 1

n2 = r - m

L = [0] * (n1)

R = [0] * (n2)

for i in range(0, n1):

L[i] = arr[l + i]

for j in range(0, n2):

R[j] = arr[m + 1 + j]

i=0
j=0
k=l
while i < n1 and j < n2:

if L[i] <= R[j]:

arr[k] = L[i]

i += 1

else:

arr[k] = R[j]

j += 1

k += 1
while i < n1:

arr[k] = L[i]

i += 1

k += 1

while j < n2:

arr[k] = R[j]

j += 1

4
Analysis & Design Of Algorithms

k += 1

def mergeSort(arr, l, r):

if l < r:

m = l+(r-l)//2

mergeSort(arr, l, m)

mergeSort(arr, m+1, r)

merge(arr, l, m, r)

arr = [12, 11, 13, 5, 6, 7]

n = len(arr)

print("Given array is")

for i in range(n):

print("%d" % arr[i],end=" ")

mergeSort(arr, 0, n-1)

print("\n\nSorted array is")

for i in range(n):

print("%d" % arr[i],end=" ")

Output:
Given array is
12 11 13 5 6 7
Sorted array is
5 6 7 11 12 13

5
Analysis & Design Of Algorithms

Quicksort Sort
def partition(array, low, high):

pivot = array[high]

i = low - 1

for j in range(low, high):

if array[j] <= pivot:

i=i+1

(array[i], array[j]) = (array[j], array[i])

(array[i + 1], array[high]) = (array[high], array[i + 1])

return i + 1

def quickSort(array, low, high):

if low < high:

pi = partition(array, low, high)

quickSort(array, low, pi - 1)

quickSort(array, pi + 1, high)

data = [1, 7, 4, 1, 10, 9, -2]

print("Unsorted Array")

print(data)

size = len(data)

quickSort(data, 0, size - 1)

print('Sorted Array in Ascending Order:')

print(data)

Output:
Unsorted Array
[1, 7, 4, 1, 10, 9, -2]
Sorted Array in Ascending Order:
[-2, 1, 1, 4, 7, 9, 10]

6
Analysis & Design Of Algorithms

Time Complexity:

Algorithm Best case Average case Worst case


Bubble sort O(n) O(n^2) O(n^2)
Selection sort O(n^2) O(n^2) O(n^2)
Insertion Sort O(n) O(n^2) O(n^2)
Merge sort O(n log(n)) O(n log(n)) O(n log(n))
Quick sort O(n log n) O(n log n) O(n^2)

7
Analysis & Design Of Algorithms

Practical-2
Aim:Implementation and Time analysis of linear and binary search
algorithm.

Linear search:

def linear_Search(list1, n, key):  

      for i in range(0, n):  

        if (list1[i] == key):  

            return i  

    return -1  

list1 = [1 ,3, 5, 4, 7, 9]  

key = 7  

  

n = len(list1)  

res = linear_Search(list1, n, key)  

if(res == -1):  

    print("Element not found")  

else:  

    print("Element found at index: ", res)  

Output:

Element found at index: 4

Binary Search:

def binary_search(list1, n):  

    low = 0  

8
Analysis & Design Of Algorithms

    high = len(list1) - 1  

    mid = 0  

  while low <= high:  

        mid = (high + low) // 2  

        if list1[mid] < n:  

            low = mid + 1  

        elif list1[mid] > n:  

            high = mid - 1  

        else:  

            return mid  

  return -1    

list1 = [12, 24, 32, 39, 45, 50, 54]  

n = 45    

result = binary_search(list1, n)  

  

if result != -1:  

    print("Element is present at index", str(result))  

else:  

    print("Element is not present in list1")  

Output:

Element is present at index 4

9
Analysis & Design Of Algorithms

Time complexity:

Algorithm Best Case Average case Worst Case

Binary Search O(1) O(logn) O(logn)

Linear Search O(1) O(n) O(n)

10
Analysis & Design Of Algorithms

Practical-3
Aim:Implementation of max-heap sort algorithm.
def heapify(arr, N, i):

largest = i # Initialize largest as root

l=2*i+1 # left = 2*i + 1

r=2*i+2 # right = 2*i + 2

if l < N and arr[largest] < arr[l]:

largest = l

if r < N and arr[largest] < arr[r]:

largest = r

if largest != i:

arr[i], arr[largest] = arr[largest], arr[i] # swap

heapify(arr, N, largest)

def heapSort(arr):

N = len(arr)

for i in range(N//2 - 1, -1, -1):

heapify(arr, N, i)

for i in range(N-1, 0, -1):

arr[i], arr[0] = arr[0], arr[i] # swap

heapify(arr, i, 0)

if __name__ == '__main__':

arr = [12, 11, 13, 5, 6, 7]

heapSort(arr)

N = len(arr)
print("Sorted array is")

for i in range(N):

11
Analysis & Design Of Algorithms

print("%d" % arr[i], end=" ")

Output:

Sorted array is

5 6 7 11 12 13

Time Complexity:

Algorithm Best case Average case Worst case


Max heap sort O(logn) O(logn) O(logn)

12
Analysis & Design Of Algorithms

Practical-4
Aim:Implementation and Time analysis of factorial program using
iterative and recursive method

recursive method:
def recur_factorial(n):  
   if n == 1:  
       return n  
   else:  
       return n*recur_factorial(n-1)  
# take input from the user  
num = int(input("Enter a number: "))  
# check is the number is negative  
if num < 0:  
    print("Sorry, factorial does not exist for negative numbers")  
elif num == 0:  
    print("The factorial of 0 is 1")  
else:  
    print("The factorial of",num,"is",recur_factorial(num))

Output:

Iterative method:
def factorial(x):

if x == 1:

return 1

else:

return (x * factorial(x-1))

13
Analysis & Design Of Algorithms

num = 7

result = factorial(num)

print("The factorial of", num, "is", result)

Output:

Time Complexity:

Algorithm Best case Average case Worst case


Iterative O(n) O(n) O(n)
Recursive O(n) O(n) O(n)

14
Analysis & Design Of Algorithms

Practical-5
AIM:Implementation of a knapsack problem using dynamic programming

def knapSack(W, wt, val, n):

K = [[0 for x in range(W + 1)] for x in range(n + 1)]

# Build table K[][] in bottom up manner

for i in range(n + 1):

for w in range(W + 1):

if i == 0 or w == 0:

K[i][w] = 0

elif wt[i-1] <= w:

K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w])

else:

K[i][w] = K[i-1][w]

return K[n][W]

val = [60, 100, 120]

wt = [10, 20, 30]

W = 50

n = len(val)

print(knapSack(W, wt, val, n))

Output:
220

15
Analysis & Design Of Algorithms

Time Complexity:

Algorithm Best case Average case Worst case


Knapsack O(n*w) O(n*w) O(n*w)

16
Analysis & Design Of Algorithms

Practical-6
Aim:Implementation of chain matrix multiplication using dynamic
programming
import sys

def MatrixChainOrder(p, i, j):

if i == j:

return 0

_min = sys.maxsize

for k in range(i, j):


count = (MatrixChainOrder(p, i, k)

+ MatrixChainOrder(p, k + 1, j)

+ p[i-1] * p[k] * p[j])

if count < _min:

_min = count;

return _min;

arr = [1, 2, 3, 4, 3];

n = len(arr);

print("Minimum number of multiplications is ",

MatrixChainOrder(arr, 1, n-1));

OutPut:

Minimum number of multiplication is 30

17
Analysis & Design Of Algorithms

Time Complexity:

Algorithm Best case Average case Worst case


Chain matrix O(n^2) O(n^2) O(n^3)
multiplication

18
Analysis & Design Of Algorithms

Practical-7
Aim:Implementation of making a change problem using dynamic
programming

def count(S, m, n):


table = [[0 for x in range(m)] for x in range(n+1)]

for i in range(m):
table[0][i] = 1

for i in range(1, n+1):


for j in range(m):
x = table[i - S[j]][j] if i-S[j] >= 0 else 0
y = table[i][j-1] if j >= 1 else 0
table[i][j] = x + y
return table[n][m-1]
arr = [1, 2, 3]
m = len(arr)
n=4
print(count(arr, m, n))

Output:
4

Time Complexity:

Algorithm Best case Average case Worst case


Making chance O(n*c) O(n*c) O(n*c)
problem

19
Analysis & Design Of Algorithms

Practical-8
Aim:Implementation of a knapsack problem using greedy algorithm
class Item:
def __init__(self, value, weight):
self.value = value
self.weight = weight

def fractionalKnapsack(W, arr):


arr.sort(key=lambda x: (x.value/x.weight), reverse=True)

finalvalue = 0.0
for item in arr:

if item.weight <= W:
W -= item.weight
finalvalue += item.value
else:
finalvalue += item.value * W / item.weight
break
return finalvalue

if __name__ == "__main__":
W = 50
arr = [Item(60, 10), Item(100, 20), Item(120, 30)]
max_val = fractionalKnapsack(W, arr)
print(max_val)

20
Analysis & Design Of Algorithms

Output:
240.0

Time Complexity:

Algorithm Best case Average case Worst case


knapsack O(nlogn). O(nlogn). O(nlogn).
problem using
greedy
algorithm

21
Analysis & Design Of Algorithms

Practical-9
Aim:Implementation of Graph and Searching (DFS and BFS).

from collections import defaultdict


class Graph:
def __init__(self):

self.graph = defaultdict(list)

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

def BFS(self, s):


visited = [False] * (max(self.graph) + 1)
queue = []
queue.append(s)
visited[s] = True

while queue:

s = queue.pop(0)
print (s, end = " ")

for i in self.graph[s]:
if visited[i] == False:
queue.append(i)
visited[i] = True

g = Graph()

22
Analysis & Design Of Algorithms

g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)

print ("Following is Breadth First Traversal"


" (starting from vertex 2)")
g.BFS(2)

Output:

23
Analysis & Design Of Algorithms

Depth First Search:


from collections import defaultdict
class Graph:
def __init__(self):

self.graph = defaultdict(list)
def addEdge(self, u, v):
self.graph[u].append(v)
def DFSUtil(self, v, visited):

visited.add(v)
print(v, end=' ')
for neighbour in self.graph[v]:
if neighbour not in visited:
self.DFSUtil(neighbour, visited)
def DFS(self, v):
visited = set()

self.DFSUtil(v, visited)
if __name__ == "__main__":
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
print("Following is DFS from (starting from vertex 2)")
g.DFS(2)

24
Analysis & Design Of Algorithms

Output:

Time Complexity:

Algorithm Best case Average case Worst case


DFS O(V+E) O(V+E) O(V+E)
BFS O(V+E) O(V+E) O(V+E)

25
Analysis & Design Of Algorithms

Practical-10
Aim:Implement prim’s algorithm.

We have discussed Kruskal’s algorithm for Minimum Spanning Tree. Like Kruskal’s
algorithm, Prim’s algorithm is also a Greedy algorithm. Prim’s algorithm always starts with a
single node and it moves through several adjacent nodes, in order to explore all of the
connected edges along the way.
import sys
class Graph():

def __init__(self, vertices):


self.V = vertices
self.graph = [[0 for column in range(vertices)]
for row in range(vertices)]
def printMST(self, parent):
print("Edge \tWeight")
for i in range(1, self.V):
print(parent[i], "-", i, "\t", self.graph[i][parent[i]])

def minKey(self, key, mstSet):


min = sys.maxsize

for v in range(self.V):
if key[v] < min and mstSet[v] == False:
min = key[v]
min_index = v

return min_index
def primMST(self):

key = [sys.maxsize] * self.V

26
Analysis & Design Of Algorithms

parent = [None] * self.V # Array to store constructed MST


key[0] = 0
mstSet = [False] * self.V

parent[0] = -1 # First node is always the root of

for cout in range(self.V):


u = self.minKey(key, mstSet)
mstSet[u] = True
for v in range(self.V):
if self.graph[u][v] > 0 and mstSet[v] == False and key[v] > self.graph[u][v]:
key[v] = self.graph[u][v]
parent[v] = u

self.printMST(parent)
if __name__ == '__main__':
g = Graph(5)
g.graph = [[0, 2, 0, 6, 0],
[2, 0, 3, 8, 5],
[0, 3, 0, 0, 7],
[6, 8, 0, 0, 9],
[0, 5, 7, 9, 0]]

g.primMST()

27
Analysis & Design Of Algorithms

Output:

Time Complexity:

Algorithm Best case Average case Worst case


Prims O(E + logV) O(E + logV) O(E + logV)
Algorithm

28
Analysis & Design Of Algorithms

Practical-11
Aim:Implement kruskal’s algorithm.
class Graph:

def __init__(self, vertices):


self.V = vertices # No. of vertices
self.graph = []
def addEdge(self, u, v, w):
self.graph.append([u, v, w])
def find(self, parent, i):
if parent[i] != i:
parent[i] = self.find(parent, parent[i])
return parent[i]
def union(self, parent, rank, x, y):
if rank[x] < rank[y]:
parent[x] = y
elif rank[x] > rank[y]:
parent[y] = x

else:
parent[y] = x
rank[x] += 1
def KruskalMST(self):

result = [] # This will store the resultant MST


i=0
e=0
self.graph = sorted(self.graph,

29
Analysis & Design Of Algorithms

key=lambda item: item[2])

parent = []
rank = []
for node in range(self.V):
parent.append(node)
rank.append(0)
while e < self.V - 1:
u, v, w = self.graph[i]
i=i+1
x = self.find(parent, u)
y = self.find(parent, v)

if x != y:
e=e+1
result.append([u, v, w])
self.union(parent, rank, x, y)

minimumCost = 0
print("Edges in the constructed MST")
for u, v, weight in result:
minimumCost += weight
print("%d -- %d == %d" % (u, v, weight))
print("Minimum Spanning Tree", minimumCost)
if __name__ == '__main__':
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)

30
Analysis & Design Of Algorithms

g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)

g.KruskalMST()

Output:

Time Complexity:

Algorithm Best case Average case Worst case


Kruskal’s O(E log V) O(E log V) O(E log V)
algorithm.

31
Analysis & Design Of Algorithms

Practical-12
Aim:Implement LCS problem.
def lcs(X, Y, m, n):

if m == 0 or n == 0:
return 0
elif X[m-1] == Y[n-1]:
return 1 + lcs(X, Y, m-1, n-1);
else:
return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));
X = "AGGTAB"
Y = "GXTXAYB"
print ("Length of LCS is ", lcs(X , Y, len(X), len(Y)) )

Output:

Time Complexity:

Algorithm Best case Average case Worst case


LCS Problem O(n * m) O(n * m) O(n * m)

32

You might also like