0% found this document useful (0 votes)
166 views34 pages

CD3281 DS Lab Manual

DS LAB MANUAL

Uploaded by

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

CD3281 DS Lab Manual

DS LAB MANUAL

Uploaded by

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

Ex:No: 1 Simple ADT As Python Classes

class check:
def __init__(self):
self.n=[]
def add(self,a):
return self.n.append(a)
def remove(self,b):
self.n.remove(b)
def dis(self):
return(self,n)

obj1=check()
choice=1
while choice!=0:
print("0. Exit")
print("1. Add")
print("2. Delete")
print("3. Dispaly")
choice=int(input("Enter the choice"))
if(choice==1):
n=int(input("Enter number to append"))
obj1.add(n)
print("List",obj1.dis())
elif choice==2:
n=int(input("Enter number to remove"))
obj1.remove(n)
print("List",obj1.dis())
elif choice==3:
print("List",obj1.dis())
elif choice==0:
print("Exiting!")
else:
print("Invalid Choice")
print()

Output:
0. Exit
1. Add
2. Delete
3. Dispaly
Enter the choice 1
Enter number to append 23
List [23]

0. Exit
1. Add
2. Delete
3. Dispaly
Enter the choice 1
Enter number to append 45
List [23, 45]

0. Exit
1. Add
2. Delete
3. Dispaly
Enter the choice 1
Enter number to append 56
List [23, 45, 56]
0. Exit
1. Add
2. Delete
3. Dispaly
Enter the choice 3
List [23, 45, 56]

0. Exit
1. Add
2. Delete
3. Dispaly
Enter the choice 2
Enter number to remove 45
List [23, 56]

0. Exit
1. Add
2. Delete
3. Dispaly
Enter the choice 3
List [23, 56]

0. Exit
1. Add
2. Delete
3. Dispaly
Enter the choice 0
Exit

Ex:No: 2 a Implementation of Recursive Algorithm (Factorial)


def factorial(n):
if(n<=1):
return 1
else:
return(n*factorial(n-1))
n=int(input("Enter number"))
print("Factorial")
print(factorial(n))

Output:
Enter number 5
Factorial
120
Ex:No: 2 b Implementation of Recursive Algorithm (Fibonacci Series)
def recur_fibo(n):
if n <= 1:
return n
else:
return(recur_fibo(n-1) + recur_fibo(n-2))

nterms = int(input("How many terms? "))


if nterms <= 0:
print("Plese enter a positive integer")
else:
print("Fibonacci sequence:")
for i in range(nterms):
print(recur_fibo(i))

output:
How many terms? 10
Fibonacci sequence:
0
1
1
2
3
5
8
13
21
34

Ex:No:3 List ADT using Python Arrays


import array
arr=array.array('i',[1,2,3])
print("The new created array is ",end="")
for i in range(0,3):
print(arr[i],end="")
print("\t")
arr.append(4)
print("The appended array is")
for i in range(0,4):
print(arr[i],"\t",end="")
arr.insert(2,5)
print("\t")
print("The array after insertion is ",end="")
for i in range(0,5):
print(arr[i],"\t",end="")
Output:
The new created array is: 1 2 3
The appended array is: 1 2 3 4
The array after insertion is: 1 2 5 3 4
Ex:No:4 a Singly Linked List
class Node:
def __init__(self,data):
self.data=data
self.next=None

class singlylinkedlist:
def __init__(self):
self.head=None
def display(self):
temp=self.head
if self.head is None:
print("empty")
while temp is not None:
print(temp.data,end="\t")
temp=temp.next
def insertatbeg(self,data):
newNode=Node(data)
newNode.next=self.head
self.head=newNode

def insertatend(self,data):
newNode=Node(data)
temp=self.head
while temp.next is not None:
temp=temp.next
temp.next=newNode

def insertatintermediate(self,data):
newNode=Node(data)
temp=self.head
pos=3
for i in range(1,pos-1):
temp=temp.next
newNode.next=temp.next
temp.next=newNode

list1=singlylinkedlist()
Node1=Node(10)
list1.head=Node1
Node2=Node(20)
Node1.next=Node2
Node3=Node(30)
Node2.next=Node3
Node4=Node(40)
Node3.next=Node4
print("Node Creation")
list1.display()
print("\n")
print("Node insert at begin\n")
list1.insertatbeg(5)
list1.display()
print("\n")
print("Node insert at end\n")
list1.insertatend(50)
list1.display()
print("\n")
print("Node insert at intermediate")
list1.insertatintermediate(15)
print("\n")
list1.display()

Output:
Node Creation
10 20 30 40
Node insert at begin
5 10 20 30 40
Node insert at end
10 20 30 40 50
Node insert at intermediate
5 10 15 20 30 40

Ex:No: 4b Doubly Linked List

class node:
def __init__(self,data):
self.data=data
self.prev=None
self.next=None

class doublylinkedlist:
def __init__(self):
self.head=None
def display(self):
temp=self.head
if self.head is None:
print("empty")
while temp is not None:
print(temp.data,end="\t")
temp=temp.next
def insertatbeg(self,data):
temp=self.head
newnode=node(5)
newnode.next=temp
temp.prev=newnode
self.head=newnode
def deletion(self,data):
temp=self.head
self.head=temp.next
self.head.prev=None
temp.next=None

list1=doublylinkedlist()
node1=node(10)
list1.head=node1
node2=node(20)
node1.next=node2
node2.prev=node1
node3=node(30)
node2.next=node3
node3.prev=node2
node4=node(40)
node3.next=node4
node4.prev=node3
print("\ndoublylinkedlist:")
list1.display()
list1.insertatbeg(5)
print("\ninsert at beg:")
list1.display()
list1.deletion(5)
print("\ndelection:")
list1.display()
Output:

doublylinkedlist:
10 20 30 40
insert at beg:
5 10 20 30 40
deletion:
10 20 30 40

Ex: No: 4 c Circular Linked List


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

class CreateList:
#Declaring head and tail pointer as null.
def __init__(self):
self.head = Node(None);
self.tail = Node(None);
self.head.next = self.tail;
self.tail.next = self.head;

#This function will add the new node at the end of the list.
def add(self,data):
newNode = Node(data);
#Checks if the list is empty.
if self.head.data is None:
#If list is empty, both head and tail would point to new node.
self.head = newNode;
self.tail = newNode;
newNode.next = self.head;
else:
#tail will point to new node.
self.tail.next = newNode;
#New node will become new tail.
self.tail = newNode;
#Since, it is circular linked list tail will point to head.
self.tail.next = self.head;

#Displays all the nodes in the list


def display(self):
current = self.head;
if self.head is None:
print("List is empty");
return;
else:
print("Nodes of the circular linked list: ");
#Prints each node by incrementing pointer.
print(current.data),
while(current.next != self.head):
current = current.next;
print(current.data),

class CircularLinkedList:
cl = CreateList();
#Adds data to the list
cl.add(1);
cl.add(2);
cl.add(3);
cl.add(4);
#Displays all the nodes present in the list
cl.display();
Output:
1
2
3
4

Ex:No: 5 a Implementation of Stack


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

def isEmpty(self):
return self.items == []

def push(self, item):


self.items.append(item)

def pop(self):
return self.items.pop()

def peek(self):
return self.items[len(self.items)-1]

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

s=Stack()
print(s.isEmpty())
s.push(4)
s.push('dog')
print(s.peek())
s.push(True)
print(s.size())
print(s.isEmpty())
s.push(8.4)
print(s.pop())
print(s.pop())
print(s.size())
OUTPUT:
True
dog
3
False
8.4
True
2

Ex:No 5b Implementation of Queue


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

def isEmpty(self):
return self.items == []

def enqueue(self,item):
self.items.append(item)

def dequeue(self):
return self.items.pop()

def front(self):
return self.items[len(self.items)-1]

def size(self):
return len(self.items)
q=Queue()
print("Queue Opeartion example")
print(q.isEmpty())
q.enqueue(5)
q.enqueue("python")
print(q.front())
q.enqueue("True")
print(q.size())
print(q.isEmpty())
q.enqueue(11.5)
print(q.dequeue())
print(q.dequeue())
print(q.size())
OUTPUT:
queue operation example
True
Python
3
False
11.5
True
2

Ex:No:6 a Applications of List

def add(A,B,m,n):
size=max(m,n)
sum=[0 for i in range(size)]
for i in range(0,m,1):
sum[i]=A[i]
for i in range(n):
sum[i]+=B[i]
return sum
def printpoly(poly,n):
for i in range(n):
print(poly[i],end=" ")
if(i!=0):
print("x^",i,end=" ")
if(i!=n-1):
print("+",end=" ")
if __name__=='__main__':
A=[5,0,10,6]
B=[1,2,4]
m=len(A)
n=len(B)
print("first polynomial is")
printpoly(A,m)
print("\n",end=" ")
print("second polynomial is:")
printpoly(B,n)
print("\n",end=" ")
sum=add(A,B,m,n)
size=max(m,n)
print("sum polynomial is:")
printpoly(sum,size)

output:
first polynomial is
5 + 0 x^ 1 + 10 x^ 2 + 6 x^ 3
second polynomial is:
1 + 2 x^ 1 + 4 x^ 2
sum polynomial is:
6 + 2 x^ 1 + 14 x^ 2 + 6 x^ 3

Ex:No:6b Applications of Stack


class stack:
def __init__(self):
self.items=[]
def is_empty(self):
return self.items==[]
def push(self,data):
self.items.append(data)
def pop(self):
return self.items.pop()
s=stack()
exp=input("please enter the expression:")
for c in exp:
if c=='(':
s.push(1)
elif c==')':
if s.is_empty():
is_balanced=False
break
s.pop()
else:
if s.is_empty():
is_balanced=True
else:
is_balanced=False
if is_balanced:
print("expression is correctly paranthesized")
else:
print("expression is not correctly paranthesized")

Output:
please enter the expression:
(a+b))(3)
expression is not correctly parenthesized
expression is not correctly parenthesized
expression is not correctly parenthesized

Ex:No: 6c Applications of Queue


class dequeue:
def __init__(self):
self.items=[]
def is_empty(self):
return self.items==[]
def append(self,data):
self.items.append(data)
def append_left(self,data):
self.items.insert(0,data)
def pop(self):
return self.items.pop(0)
def pop_left(self):
return self.items.pop(0)

q=dequeue()
print("menu")
print("append<value>")
print("appendleft<value>")
print("pop")
print("popleft")
print("quit")
while True:
do=input("what would you like to do?").split()
operation=do[0].strip().lower()
if operation=='append':
q.append(int(do[1]))
elif operation=='appendleft':
q.append_left(int(do[1]))
elif operation=='pop':
if q.is_empty():
print("dequeue is empty")
else:
print("poped value from right:",q.pop())
elif operation=='popleft':
if q.is_empty():
print("dequeue is empty")
else:
print("poped value from left:",q.pop_left())
elif operation=='quit':
break
Output:
menu
append<value>
appendleft<value>
pop
popleft
quit
what would you like to do? append 1
what would you like to do? append 2
what would you like to do? pop
Popped value from right: 2
what would you like to do? pop
Popped value from right: 1
what would you like to do? append left 1
what would you like to do? append left 2
what would you like to do? pop
Popped value from right: 1
what would you like to do? pop
Popped value from right: 2

Ex:No: 7 a Merge Sort


def mergesort(list1):
if len(list1)>1:
mid=len(list1)//2
left_list=list1[:mid]
right_list=list1[mid:]
left_list=mergesort(left_list)
right_list=mergesort(right_list)
i=0
j=0
k=0
while len(list1)>1 and i<len(left_list)and j<len(right_list):
if left_list[i]<right_list[j]:
list1[k]=left_list[i]
i=i+1
k=k+1
else:
list1[k]=right_list[j]
j=j+1
k=k+1
while len(list1)>1 and i<len(left_list):
list1[k]=left_list[i]
i=i+1
k=k+1
while len(list1)>1 and j<len(right_list):
list1[k]=right_list[j]
j=j+1
k=k+1
return list1
list1=[23,65,76,54,32,5]
print(mergesort(list1))

Output:
[5, 23, 32, 54, 65, 76]

Ex:No: 7 b Quick Sort


def partition(arr,low,high):
i = ( low-1 )
pivot = arr[high] # pivot element
for j in range(low , high):
# If current element is smaller
if arr[j] <= pivot:
# increment
i = i+1
arr[i],arr[j] = arr[j],arr[i]
arr[i+1],arr[high] = arr[high],arr[i+1]
return ( i+1 )
# sort
def quickSort(arr,low,high):
if low < high:
# index
pi = partition(arr,low,high)
# sort the partitions
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)
# main
arr = [2,5,3,8,6,5,4,7]
n = len(arr)
quickSort(arr,0,n-1)
print ("Sorted array is:")
for i in range(n):
print (arr[i],end=" ")
Output:
Sorted array is:
2 3 4 5 5 6 7
Ex:No: 7c 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("elements not found")
else:
print("element is found at index:",res)

Output:
element is found at index: 4

Ex:No: 7d Binary Search


def binary_search(a,x):
low=0
high=len(a)-1
mid=0
while low<=high:
mid=(low+high)//2
if a[mid]>x:
high=mid-1
elif a[mid]<x:
low=mid+1
else:
return mid
return -1
arr=[2,3,4,10,40]
x=10
res=binary_search(arr,x)
if res!=-1:
print("element is found at index",res)
else:
print("element is not found")

Output:
element is found at index 3

Ex:NO: 8 Implementation of Hash Table


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):


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'], [], [], [], []]

Ex:No: 9 Tree Representation and Traversal Algorithm


Inorder:
class TreeNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None

def inorderTraversal(root):
answer = []

inorderTraversalUtil(root, answer)
return answer

def inorderTraversalUtil(root, answer):

if root is None:
return

inorderTraversalUtil(root.left, answer)
answer.append(root.val)
inorderTraversalUtil(root.right, answer)
return

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print(inorderTraversal(root))

Output:
[4, 2, 5, 1, 3]

Preorder Traversal
class TreeNode:

def __init__(self,val):
self.val = val
self.left = None
self.right = None

def preorderTraversal(root):
answer = []

preorderTraversalUtil(root, answer)
return answer

def preorderTraversalUtil(root, answer):

if root is None:
return

answer.append(root.val)

preorderTraversalUtil(root.left, answer)

preorderTraversalUtil(root.right, answer)

return

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

print(preorderTraversal(root))

Output:
[1, 2, 4, 5, 3]
Postorder Traversal:

class TreeNode:

def __init__(self, val):


self.val = val
self.left = None
self.right = None

def postorderTraversal(root):
answer = []

postorderTraversalUtil(root, answer)
return answer

def postorderTraversalUtil(root, answer):

if root is None:
return

postorderTraversalUtil(root.left, answer)

postorderTraversalUtil(root.right, answer)

answer.append(root.val)

return

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

print(postorderTraversal(root))

Output:
[4, 5, 2, 3, 1]
Ex:No: 10 Implemenattion of Binary Search
Tree

# Create a node
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None

# Inorder traversal
def inorder(root):
if root is not None:
# Traverse left
inorder(root.left)

# Traverse root
print(str(root.key) + "->", end=' ')

# Traverse right
inorder(root.right)

# Insert a node
def insert(node, key):

# Return a new node if the tree is empty


if node is None:
return Node(key)

# Traverse to the right place and insert the node


if key < node.key:
node.left = insert(node.left, key)
else:
node.right = insert(node.right, key)

return node
# Find the inorder successor
def minValueNode(node):
current = node

# Find the leftmost leaf


while(current.left is not None):
current = current.left

return current

# Deleting a node
def deleteNode(root, key):

# Return if the tree is empty


if root is None:
return root

# Find the node to be deleted


if key < root.key:
root.left = deleteNode(root.left, key)
elif(key > root.key):
root.right = deleteNode(root.right, key)
else:
# If the node is with only one child or no child
if root.left is None:
temp = root.right
root = None
return temp

elif root.right is None:


temp = root.left
root = None
return temp

# If the node has two children,


# place the inorder successor in position of the node to be deleted
temp = minValueNode(root.right)

root.key = temp.key

# Delete the inorder successor


root.right = deleteNode(root.right, temp.key)

return root

root = None
root = insert(root, 8)
root = insert(root, 3)
root = insert(root, 1)
root = insert(root, 6)
root = insert(root, 7)
root = insert(root, 10)
root = insert(root, 14)
root = insert(root, 4)

print("Inorder traversal: ", end=' ')


inorder(root)
print("\nDelete 10")
root = deleteNode(root, 10)
print("Inorder traversal: ", end=' ')
inorder(root)

Output:

Inorder traversal: 1-> 3-> 4-> 6-> 7-> 8-> 10-> 14->
Delete 10
Inorder traversal: 1-> 3-> 4-> 6-> 7-> 8-> 14->

Ex:No:11 Implementation of Heap


Program:
class BinaryHeap:
def __init__(self):
self.items = []

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

def parent(self, i):


return (i - 1)//2

def left(self, i):


return 2*i + 1

def right(self, i):


return 2*i + 2

def get(self, i):


return self.items[i]
def get_max(self):
if self.size() == 0:
return None
return self.items[0]

def extract_max(self):
if self.size() == 0:
return None
largest = self.get_max()
self.items[0] = self.items[-1]
del self.items[-1]
self.max_heapify(0)
return largest

def max_heapify(self, i):


l = self.left(i)
r = self.right(i)
if (l <= self.size() - 1 and self.get(l) > self.get(i)):
largest = l
else:
largest = i
if (r <= self.size() - 1 and self.get(r) > self.get(largest)):
largest = r
if (largest != i):
self.swap(largest, i)
self.max_heapify(largest)

def swap(self, i, j):


self.items[i], self.items[j] = self.items[j], self.items[i]

def insert(self, key):


index = self.size()
self.items.append(key)

while (index != 0):


p = self.parent(index)
if self.get(p) < self.get(index):
self.swap(p, index)
index = p

bheap = BinaryHeap()

print('Menu')
print('insert <data>')
print('max get')
print('max extract')
print('quit')

while True:
do = input('What would you like to do? ').split()

operation = do[0].strip().lower()
if operation == 'insert':
data = int(do[1])
bheap.insert(data)
elif operation == 'max':
suboperation = do[1].strip().lower()
if suboperation == 'get':
print('Maximum value: {}'.format(bheap.get_max()))
elif suboperation == 'extract':
print('Maximum value removed: {}'.format(bheap.extract_max()))

elif operation == 'quit':


break

Output:
Case 1:
Menu
insert <data>
max get
max extract
quit
What would you like to do? insert 5
What would you like to do? insert 3
What would you like to do? insert -3
What would you like to do? insert 10
What would you like to do? insert 8
What would you like to do? max get
Maximum value: 10
What would you like to do? max extract
Maximum value removed: 10
What would you like to do? max extract
Maximum value removed: 8
What would you like to do? max extract
Maximum value removed: 5
What would you like to do? max extract
Maximum value removed: 3
What would you like to do? max get
Maximum value: -3
What would you like to do? quit

Case 2:
Menu
insert <data>
max get
max extract
quit
What would you like to do? insert 3
What would you like to do? insert 11
What would you like to do? insert 5
What would you like to do? max extract
Maximum value removed: 11
What would you like to do? max get
Maximum value: 5
What would you like to do? max extract
Maximum value removed: 5
What would you like to do? insert 15
What would you like to do? max get
Maximum value: 15
What would you like to do? quit
Ex:No:12. a Implementation of Breadth First Search
Program:
from collections import defaultdict

# This class represents a directed graph


# using adjacency list representation
class Graph:

# Constructor
def __init__(self):

# default dictionary to store graph


self.graph = defaultdict(list)

# function to add an edge to graph


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

# Function to print a BFS of graph


def BFS(self, s):

# Mark all the vertices as not visited


visited = [False] * (len(self.graph))

# Create a queue for BFS


queue = []

# Mark the source node as


# visited and enqueue it
queue.append(s)
visited[s] = True

while queue:

# Dequeue a vertex from


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

# Get all adjacent vertices of the


# dequeued vertex s. If a adjacent
# has not been visited, then mark it
# visited and enqueue it
for i in self.graph[s]:
if visited[i] == False:
queue.append(i)
visited[i] = True

# Create a graph given in


# the above diagram
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 Breadth First Traversal"


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

Output:
2 0 3 1

Ex:No:12b Implementation of Depth First Search

from collections import defaultdict

# this class represents a directed graph using adjacency list representation

class Graph:
# Constructor
def __init__(self):
# default dictionary to store graph
self.graph = defaultdict(list)

# Function to add an edge to graph


def addEdge(self, u, v):
self.graph[u].append(v)
# A function used by DFS
def DFSUtil(self, v, visited):
# Mark the current node as visited and print it
visited.add(v)
print(v, end=" ")

# recur for all the vertices adjacent to this vertex


for neighbour in self.graph[v]:
if neighbour not in visited:
self.DFSUtil(neighbour, visited)
# The function to do DFS traversal. It uses recursive DFSUtil

def DFS(self):
# create a set to store all visited vertices
visited = set()
# call the recursive helper function to print DFS traversal starting from all
# vertices one by one
for vertex in self.graph:
if vertex not in visited:
self.DFSUtil(vertex, visited)
# Driver's code
# create a graph given in the above diagram
if __name__ == "__main__":
print("Following is Depth First Traversal \n")
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)
g.DFS()
Output:
0 1 2 3
Ex:No:13 Implementation of Single Source Shortest Path Algorithm
Program:
class Graph:
def __init__(self):
# dictionary containing keys that map to the corresponding vertex object
self.vertices = {}

def add_vertex(self, key):


"""Add a vertex with the given key to the graph."""
vertex = Vertex(key)
self.vertices[key] = vertex

def get_vertex(self, key):


"""Return vertex object with the corresponding key."""
return self.vertices[key]

def __contains__(self, key):


return key in self.vertices

def add_edge(self, src_key, dest_key, weight=1):


"""Add edge from src_key to dest_key with given weight."""
self.vertices[src_key].add_neighbour(self.vertices[dest_key], weight)

def does_edge_exist(self, src_key, dest_key):


"""Return True if there is an edge from src_key to dest_key."""
return self.vertices[src_key].does_it_point_to(self.vertices[dest_key])

def __iter__(self):
return iter(self.vertices.values())

class Vertex:
def __init__(self, key):
self.key = key
self.points_to = {}

def get_key(self):
"""Return key corresponding to this vertex object."""
return self.key

def add_neighbour(self, dest, weight):


"""Make this vertex point to dest with given edge weight."""
self.points_to[dest] = weight

def get_neighbours(self):
"""Return all vertices pointed to by this vertex."""
return self.points_to.keys()

def get_weight(self, dest):


"""Get weight of edge from this vertex to dest."""
return self.points_to[dest]

def does_it_point_to(self, dest):


"""Return True if this vertex points to dest."""
return dest in self.points_to

def dijkstra(g, source):


"""Return distance where distance[v] is min distance from source to v.

This will return a dictionary distance.

g is a Graph object.
source is a Vertex object in g.
"""
unvisited = set(g)
distance = dict.fromkeys(g, float('inf'))
distance[source] = 0

while unvisited != set():


# find vertex with minimum distance
closest = min(unvisited, key=lambda v: distance[v])

# mark as visited
unvisited.remove(closest)

# update distances
for neighbour in closest.get_neighbours():
if neighbour in unvisited:
new_distance = distance[closest] + closest.get_weight(neighbour)
if distance[neighbour] > new_distance:
distance[neighbour] = new_distance

return distance
g = Graph()
print('Undirected Graph')
print('Menu')
print('add vertex <key>')
print('add edge <src> <dest> <weight>')
print('shortest <source vertex key>')
print('display')
print('quit')

while True:
do = input('What would you like to do? ').split()

operation = do[0]
if operation == 'add':
suboperation = do[1]
if suboperation == 'vertex':
key = int(do[2])
if key not in g:
g.add_vertex(key)
else:
print('Vertex already exists.')
elif suboperation == 'edge':
src = int(do[2])
dest = int(do[3])
weight = int(do[4])
if src not in g:
print('Vertex {} does not exist.'.format(src))
elif dest not in g:
print('Vertex {} does not exist.'.format(dest))
else:
if not g.does_edge_exist(src, dest):
g.add_edge(src, dest, weight)
g.add_edge(dest, src, weight)
else:
print('Edge already exists.')

elif operation == 'shortest':


key = int(do[1])
source = g.get_vertex(key)
distance = dijkstra(g, source)
print('Distances from {}: '.format(key))
for v in distance:
print('Distance to {}: {}'.format(v.get_key(), distance[v]))
print()

elif operation == 'display':


print('Vertices: ', end='')
for v in g:
print(v.get_key(), end=' ')
print()

print('Edges: ')
for v in g:
for dest in v.get_neighbours():
w = v.get_weight(dest)
print('(src={}, dest={}, weight={}) '.format(v.get_key(),
dest.get_key(), w))
print()

elif operation == 'quit':


break

Output:
Case 1:
Undirected Graph
Menu
add vertex <key>
add edge <src> <dest> <weight>
shortest <source vertex key>
display
quit
What would you like to do? add vertex 1
What would you like to do? add vertex 2
What would you like to do? add vertex 3
What would you like to do? add vertex 4
What would you like to do? add vertex 5
What would you like to do? add vertex 6
What would you like to do? add vertex 7
What would you like to do? add edge 1 2 10
What would you like to do? add edge 1 3 80
What would you like to do? add edge 3 4 70
What would you like to do? add edge 2 5 20
What would you like to do? add edge 2 3 6
What would you like to do? add edge 5 6 50
What would you like to do? add edge 5 7 10
What would you like to do? add edge 6 7 5
What would you like to do? shortest 1
Distances from 1:
Distance to 6: 45
Distance to 3: 16
Distance to 4: 86
Distance to 5: 30
Distance to 2: 10
Distance to 7: 40
Distance to 1: 0

What would you like to do? quit

Case 2:
Undirected Graph
Menu
add vertex <key>
add edge <src> <dest> <weight>
shortest <source vertex key>
display
quit
What would you like to do? add vertex 1
What would you like to do? add vertex 2
What would you like to do? add vertex 3
What would you like to do? add vertex 4
What would you like to do? add edge 1 2 10
What would you like to do? add edge 2 3 20
What would you like to do? add edge 3 4 30
What would you like to do? add edge 1 4 100
What would you like to do? shortest 1
Distances from 1:
Distance to 2: 10
Distance to 4: 60
Distance to 3: 30
Distance to 1: 0

Ex:No:14. Implementation of Minimum Spanning Tree


class Graph:
def __init__(self):
# dictionary containing keys that map to the corresponding vertex object
self.vertices = {}

def add_vertex(self, key):


"""Add a vertex with the given key to the graph."""
vertex = Vertex(key)
self.vertices[key] = vertex

def get_vertex(self, key):


"""Return vertex object with the corresponding key."""
return self.vertices[key]

def __contains__(self, key):


return key in self.vertices

def add_edge(self, src_key, dest_key, weight=1):


"""Add edge from src_key to dest_key with given weight."""
self.vertices[src_key].add_neighbour(self.vertices[dest_key], weight)

def does_vertex_exist(self, key):


return key in self.vertices

def does_edge_exist(self, src_key, dest_key):


"""Return True if there is an edge from src_key to dest_key."""
return self.vertices[src_key].does_it_point_to(self.vertices[dest_key])

def display(self):
print('Vertices: ', end='')
for v in self:
print(v.get_key(), end=' ')
print()

print('Edges: ')
for v in self:
for dest in v.get_neighbours():
w = v.get_weight(dest)
print('(src={}, dest={}, weight={}) '.format(v.get_key(),
dest.get_key(), w))

def __len__(self):
return len(self.vertices)

def __iter__(self):
return iter(self.vertices.values())

class Vertex:
def __init__(self, key):
self.key = key
self.points_to = {}

def get_key(self):
"""Return key corresponding to this vertex object."""
return self.key

def add_neighbour(self, dest, weight):


"""Make this vertex point to dest with given edge weight."""
self.points_to[dest] = weight

def get_neighbours(self):
"""Return all vertices pointed to by this vertex."""
return self.points_to.keys()

def get_weight(self, dest):


"""Get weight of edge from this vertex to dest."""
return self.points_to[dest]

def does_it_point_to(self, dest):


"""Return True if this vertex points to dest."""
return dest in self.points_to

def mst_krusal(g):
"""Return a minimum cost spanning tree of the connected graph g."""
mst = Graph() # create new Graph object to hold the MST

if len(g) == 1:
u = next(iter(g)) # get the single vertex
mst.add_vertex(u.get_key()) # add a copy of it to mst
return mst

# get all the edges in a list


edges = []
for v in g:
for n in v.get_neighbours():
# avoid adding two edges for each edge of the undirected graph
if v.get_key() < n.get_key():
edges.append((v, n))

# sort edges
edges.sort(key=lambda edge: edge[0].get_weight(edge[1]))

# initially, each vertex is in its own component


component = {}
for i, v in enumerate(g):
component[v] = i

# next edge to try


edge_index = 0

# loop until mst has the same number of vertices as g


while len(mst) < len(g):
u, v = edges[edge_index]
edge_index += 1

# if adding edge (u, v) will not form a cycle


if component[u] != component[v]:

# add to mst
if not mst.does_vertex_exist(u.get_key()):
mst.add_vertex(u.get_key())
if not mst.does_vertex_exist(v.get_key()):
mst.add_vertex(v.get_key())
mst.add_edge(u.get_key(), v.get_key(), u.get_weight(v))
mst.add_edge(v.get_key(), u.get_key(), u.get_weight(v))

# merge components of u and v


for w in g:
if component[w] == component[v]:
component[w] = component[u]

return mst

g = Graph()
print('Undirected Graph')
print('Menu')
print('add vertex <key>')
print('add edge <src> <dest> <weight>')
print('mst')
print('display')
print('quit')

while True:
do = input('What would you like to do? ').split()

operation = do[0]
if operation == 'add':
suboperation = do[1]
if suboperation == 'vertex':
key = int(do[2])
if key not in g:
g.add_vertex(key)
else:
print('Vertex already exists.')
elif suboperation == 'edge':
src = int(do[2])
dest = int(do[3])
weight = int(do[4])
if src not in g:
print('Vertex {} does not exist.'.format(src))
elif dest not in g:
print('Vertex {} does not exist.'.format(dest))
else:
if not g.does_edge_exist(src, dest):
g.add_edge(src, dest, weight)
g.add_edge(dest, src, weight)
else:
print('Edge already exists.')

elif operation == 'mst':


mst = mst_krusal(g)
print('Minimum Spanning Tree:')
mst.display()
print()

elif operation == 'display':


g.display()
print()

elif operation == 'quit':


break

Output:
Case 1:
Undirected Graph
Menu
add vertex <key>
add edge <src> <dest> <weight>
mst
display
quit
What would you like to do? add vertex 1
What would you like to do? add vertex 2
What would you like to do? add vertex 3
What would you like to do? add vertex 4
What would you like to do? add vertex 5
What would you like to do? add vertex 6
What would you like to do? add edge 1 2 10
What would you like to do? add edge 1 5 30
What would you like to do? add edge 1 4 40
What would you like to do? add edge 2 5 20
What would you like to do? add edge 4 5 40
What would you like to do? add edge 5 3 40
What would you like to do? add edge 5 6 70
What would you like to do? add edge 3 6 50
What would you like to do? mst
Minimum Spanning Tree:
Vertices: 1 2 3 4 5 6
Edges:
(src=1, dest=4, weight=40)
(src=1, dest=2, weight=10)
(src=2, dest=5, weight=20)
(src=2, dest=1, weight=10)
(src=3, dest=5, weight=40)
(src=3, dest=6, weight=50)
(src=4, dest=1, weight=40)
(src=5, dest=2, weight=20)
(src=5, dest=3, weight=40)
(src=6, dest=3, weight=50)

What would you like to do? quit

Case 2:
Undirected Graph
Menu
add vertex <key>
add edge <src> <dest> <weight>
mst
display
quit
What would you like to do? add vertex 1
What would you like to do? add vertex 2
What would you like to do? add vertex 3
What would you like to do? add edge 1 2 10
What would you like to do? add edge 1 3 20
What would you like to do? add edge 2 3 30
What would you like to do? mst
Minimum Spanning Tree:
Vertices: 1 2 3
Edges:
(src=1, dest=3, weight=20)
(src=1, dest=2, weight=10)
(src=2, dest=1, weight=10)
(src=3, dest=1, weight=20)

What would you like to do? quit

You might also like