Technical Skills II Manual
Technical Skills II Manual
MODULE 1
ARRAYS
Basic operations on arrays: Traversal-insertion-deletion-search-update, Array types:
One dimensional Array-Two dimensional array.
MODULE 2
LINEAR DATA STRUCTURES
List ADT: Creating a list, Types of List-Singly linked list & operations, Doubly linked
list & operations, Circularly linked list & operations, Queue ADT-Queue using list &
operations-Queue using linked list, Stack ADT- Stack using list &operations- -Stack
using linked list-Applications of Stack-Postfix and Infix operations.
MODULE 3
NON-LINEAR DATA STRUCTURES
Trees: Binary tree traversal – In Order-Pre Order-Post Order, B-Tree, Binary heaps,
Graphs-Graph Traversal Algorithms-Breadth First Search-Depth First Search-
Topological Sorting, Shortest path algorithms-Dijikstra Algorithm-Bellman Ford
algorithm, Minimum Spanning Tree-Kruskal Algorithm-Prim’s Algorithm, All pair
shortest path – Floyd’s Algorithm.
MODULE 4
SEARCHING TECHNIQUES
Linear Search, Binary Search: Recursive Binary Search-Iterative Binary Search.
MODULE 5
SORTING TECHNIQUES AND HASHING FUCTIONS
Sorting algorithms: Bubble sort -Insertion Sort-Selection Sort-Quick Sort-Merge Sort-
Radix Sort-Bucket Sort-Heap Sort-Shell Sort- Hashing-Hash Table using Open
Addressing.
TECHNICAL SKILLS II LABORATORY
COURSE OBJECTIVES:
The course should enable the students to:
I. To understand the concepts of Arrays, ListADT.
II. To learn linear data structures–stacks and queues ADTs.
III. To understand and apply Tree data structures.
IV. To analyze sorting and searching algorithms.
V. To understand and apply Graph structures and hashing techniques.
LIST OF EXPERIMENTS
3
WEB REFERENCES:
1. https://docs.python.org/3/tutorial/datastructures.html
2. http://interactivepython.org/runestone/static/pythonds/index.html
3. http://www.tutorialspoint.com/data_structures_algorithms
4. http://www.geeksforgeeks.org/data-structures/
5. http://www.studytonight.com/data-structures/
6. http://www.coursera.org/specializations/data-structures-algorithms
3
WEEK-1
AIM:
To implement the following Array operations.
a. Append()
b. Insert()
c. Pop()
d. Remove()
e. Reverse()
EXERCISE-1
Write a Python program to append an element in an array.
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("\r")
arr.append(4);
print("The appended array is : ", end="")
for i in range (len(arr)):
print (arr[i], end=" ")
Test case-1
The new created array is : 1 2 3
Expected output
The appended array is : 1 2 3 4
EXERCISE-2
Write a Python program to insert an element in an array.
Test case-1
The new created array is : 1 2 3
Expected output-1
The array after insertion is : 1 2 5 3
Test case-2
The new created array is : 1 2 3 4
Expected output-2
The array after insertion is : 1 2 3 4 6
EXERCISE-3
Write a Python program to pop an element in an array.
Test case
The new created array is : 1 2 3 1 5
The popped element is : 3
Expected output
The array after popping is : 1 2 1 5
EXERCISE-4
Write a Python program to remove an element in an array.
Test case
The new created array is : 1 2 3 1 5
Expected output
The array after removing is : 2 3 1 5
EXERCISE-5
Write a Python program to reverse an element in an array.
Test case
The new created array is : 1 2 3 1 2 5
Expected output
The array after reversing is : 5 2 1 3 2 1
RESULT
Thus, the programs were implemented to append, insert, pop, remove and reverse the elements
in the given array.
WEEK-1
ARRAY TYPES-
AIM:
To implement the array types of One dimensional and Two dimensional array in data structures.
EXERCISE-1
Write a program using one dimensional array to update an array after changing an element in
an array and also to find the sum of the elements in the array.
myArray = [10, 20, 30, 40, 50]
print("Elements of the array:")
for i in range(5):
print(myArray[i], end=" ")
print()
myArray[2] = 35
print("Updated array after changing the third element:")
for i in range(5):
print(myArray[i], end=" ")
print()
sum_value = sum(myArray)
print("Sum of the elements:", sum_value)
Test case
Elements of the array:
10 20 30 40 50
Expected output
Updated array after changing the third element:
10 20 35 40 50
Sum of the elements: 155
EXERCISE-2
Write a program to the create and manipulate a 3x4 matrix to print the original matrix, modify
an element, calculate the sum of elements in each row, and transposes the matrix.
def print_array(array):
for row in array:
for element in row:
print(element, end="\t")
print()
rows = 3
columns = 4
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]
print("Original Matrix:")
print_array(matrix)
print("\nElement at matrix[1][2]:", matrix[1][2])
matrix[1][2] = 20
print("Modified Matrix:")
print_array(matrix)
for i in range(rows):
row_sum = sum(matrix[i])
print(f"\nSum of elements in Row {i + 1}: {row_sum}")
print("\nTransposed Matrix:")
for i in range(columns):
for j in range(rows):
print(matrix[j][i], end="\t")
print()
Test case-1
Original Matrix:
1 2 3 4
5 6 7 8
9 10 11 12
Expected output-1
Element at matrix[1][2]: 7
Modified Matrix:
1 2 3 4
5 6 20 8
9 10 11 12
Transposed Matrix:
1 5 9
2 6 10
3 20 11
4 8 12
RESULT
Thus, the programs were implemented for the one dimensional and two dimensional arrays with its
operations .
WEEK-2
IMPLEMENTATION OF SINGLE LINKED LIST
AIM
To write Python program to perform the following operations on single linked list.
(i) Creation (ii) insertion (iii) deletion (iv) traversal
1. A singly linked list's node is divided into two parts. The first part holds or points to information
about the node, and second part holds the address of next node. A singly linked list travels one
way.
2. The beginning of the linked list is stored in a "start" pointer which points to the first node. The
first node contains a pointer to the second node. The second node contains a pointer to the third
node, ... and so on.
3. The last node in the list has its next field set to NULL to mark the end of the list.
4. The basic operations in a single linked list are: Creation, Insertion, Deletion, Traversing.
SOURCE CODE:
class Node:
def init (self,data):
print("Node created",data)
self.data=data
self.next=None
class S_L_List:
def init (self):
self.head=None
self.ctr=0
def insert_beginning(self,data):
node=Node(data)
if self.head==None:
self.head=node
else:
node.next=self.head
self.head=node
self.ctr+=1
print("Node inserted",data)
return
def insert_middle(self,pos,data):
if pos==0:
self.insert_beginning(data)
elif pos==self.ctr+1:
self.insert_end(data)
else:
node=Node(data)
temp=self.head
i=0
while (i<pos-1):
temp=temp.next
i+=1
node.next=temp.next
temp.next=node
self.ctr+=1
print("Node inserted",data)
return
def insert_end(self,data):
node=Node(data)
node.next=None
if self.head==None:
self.head=node
return
temp=self.head
while (temp.next is not None):
temp=temp.next
temp.next=node
self.ctr+=1
print("Node inserted",data)
return
def delete_beginning(self):
if self.head==None:
print("No nodes exist")
elif self.ctr==1:
print("Node deleted",self.head.data)
self.head=None
self.ctr-=1
else:
print("Node deleted",self.head.data)
self.head=self.head.next
self.ctr-=1
return
def delete_middle(self,pos):
if self.head==None:
print("No nodes exist")
elif pos==0:
self.delete_beginning()
elif pos==self.ctr:
self.delete_end()
else:
temp=self.head
prev=temp
i=0
while (i<pos):
prev=temp
temp=temp.next
i+=1
prev.next=temp.next
print("Node deleted",temp.data)
temp.next=None
self.ctr-=1
return
def delete_end(self):
if self.ctr==0:
print("No Nodes present")
elif self.ctr==1:
self.ctr=0
print("Node deleted",self.head.data)
self.head=None
else:
temp=self.head
prev=self.head
while (temp.next is not None):
prev=temp
temp=temp.next
print("Node deleted",temp.data)
prev.data=None
self.ctr-=1
return
def traverse_forward(self):
if self.head==None:
print("No nodes exist")
print("traversal forward")
temp=self.head
while (temp is not None):
print(temp.data)
temp=temp.next
def menu():
print("1. Insert at beginning")
print("2. Insert at middle")
print("3. Insert at end")
print("4. Delete at beginning")
print("5. Delete at middle")
print("6. Delete at end")
print("7. Traversal forward")
print("8. Count number of nodes")
print("9. Exit")
ch=eval(input("Enter choice:"))
return ch
AIM:
PROGRAM LOGIC:
1. In Circular single linked list the link field of the last node points back to the address of the first
node.
2. A circular linked list has no beginning and no end. It is necessary to establish a special pointer
called start pointer always pointing to the first node of the list.
3. The basic operations in a circular single linked list is: creation, insertion, deletion and
traversing.
SOURCE CODE:
class Node:
def init (self,data):
self.next=None
self.data=data
print("Node created",data)
class CLList:
def init (self):
self.head=None
self.ctr=0
def insert_beg(self,data):
node=Node(data)
if self.head==None:
self.head=node
node.next=self.head
else:
temp=self.head
while temp.next is not self.head:
temp=temp.next
temp.next=node
node.next=self.head
self.head=node
print("Node inserted",data)
self.ctr+=1
return
def insert_end(self,data):
node=Node(data)
if self.head==None:
self.head=node
node.next=self.head
else:
temp=self.head
while temp.next is not self.head:
temp=temp.next
temp.next=node
node.next=self.head
self.ctr+=1
print("Node inserted",data)
return
def insert_inter(self,pos,data):
node=Node(data)
if pos<1 or pos>self.ctr:
print("invalid position")
else:
temp=self.head
i=1
while i<pos:
temp=temp.next
i+=1
node.next=temp.next
temp.next=node
self.ctr+=1
print("Node Insered",data)
return
def delete_beg(self):
if self.head==None:
print("No Nodes exist")
elif self.ctr==1:
print("Node deleted",self.head.data)
self.head=None
self.ctr-=1
else:
print("Node deleted",self.head.data)
temp=self.head
while temp.next is not self.head:
temp=temp.next
self.head=self.head.next
temp.next=self.head
self.ctr-=1
return
def delete_end(self):
if self.head==None:
print("No Nodes exist")
elif self.ctr==1:
print("Node deleted",self.head.data)
self.head=None
self.ctr-=1
else:
temp=self.head
prev=temp
while temp.next is not self.head:
prev=temp
temp=temp.next
print("Node deleted",temp.data)
prev.next=temp.next
self.ctr-=1
return
def delete_inter(self,pos):
if self.head==None:
print("No nodes exist")
elif pos<1 or pos>self.ctr:
print("Invalid position")
elif self.ctr==1:
print("Node deleted",self.head.data)
self.head=None
self.ctr-=1
else:
temp=self.head
prev=temp
i=0
while i<pos:
prev=temp
temp=temp.next
i+=1
prev.next=temp.next
print("Node deleted",temp.data)
self.ctr-=1
return
def traverse(self):
temp=self.head
i=0
while i<self.ctr:
print(temp.data)
temp=temp.next
i+=1
return
def Menu():
print("1.Insert at beginning")
print("2.Insert at middle")
print("3.Insert at end")
print("4.Delete at beginning")
print("5.Delete at middle")
print("6.Delete at end")
print("7.Traverse Forward")
print("8.Number of nodes")
print("9.Exit")
ch=int(input("Enter choice:"))
return ch
c=CLList()
print("****************Circular Linked List**************")
while True:
ch=Menu()
if ch==1:
data=input("Enter data:")
c.insert_beg(data)
elif ch==2:
data=input("Enter data:")
pos=int(input("Enter position:"))
c.insert_inter(pos,data)
elif ch==3:
data=input("Enter data:")
c.insert_end(data)
elif ch==4:
c.delete_beg()
elif ch==5:
pos=int(input("Enter position:"))
c.delete_inter(pos)
elif ch==6:
c.delete_end()
elif ch==7:
c.traverse()
elif ch==8:
print("Number of Nodes",c.ctr)
else:
print("Exit")
break
Output:
RESULT:
AIM:
PROGRAM LOGIC:
1. In a doubly-linked list each node of the list contain two references (or links) – one to the previous
node and other to the next node. The previous link of the first node and the next linkof the last
node points to NULL.
2. A double linked list is a two-way list in which all nodes will have two links. This helps in
accessing both successor node and predecessor node from the given node position. It provides
bi-directional traversing.
3. Each node contains three fields: Left link, Data and Right link.
4. The left link points to the predecessor node and the right link points to the successor node. The
data field stores the required data.
5. The basic operations in a double linked list are: creation, insertion, deletion and traversing.
6. The beginning of the double linked list is stored in a "start" pointer which points to the first node.
The first node’s left link and last node’s right link is set to NULL.
SOURCE CODE:
class Node:
def init (self,data):
self.data=data
self.next=self.prev=None
class DLinkedList:
def init (self):
self.head=None
self.ctr=0
def insert_beg(self,data):
node=Node(data)
if self.head==None:
self.head=node
else:
node.next=self.head
self.head.prev=node
self.head=node
self.ctr +=1
print("Nodes inserted",data)
return
def insert_end(self,data):
node=Node(data)
if self.head==None:
self.head=node
else:
temp=self.head
while(temp.next is not None):
temp=temp.next
temp.next=node
node.prev=temp
self.ctr +=1
print("Node inserted",data)
return
def delete_beg(self):
if self.head==None:
print("No node exist")
else:
print("Node deleted",self.head.data)
self.head=self.head.next
self.head.prev=None
self.ctr -=1
return
def delete_end(self):
if self.head==None:
print("No nodes exist")
elif self.ctr==1:
self.ctr=0
print ("Node deleted",self.head.data)
self.head=None
else:
temp=self.head
while temp.next is not None:
temp=temp.next
print("Node deleted",temp.data)
temp=temp.prev
temp.next=None
self.ctr -=1
return
def insert_pos(self,pos,data):
if pos==0:
self.insert_beg(data)
elif pos==self.ctr:
self.insert_end(data)
else:
node=Node(data)
temp=self.head
i=1
while i<pos-1:
temp=temp.next
i +=1
node.next=temp.next
temp.next.prev=node
temp.next=node
node.prev=temp
self.ctr +=1
print("Node inserted",data)
return
def delete_pos(self,pos):
if self.head==None:
print("Node is empty")
else:
if pos==0:
self.delete_beg()
elif pos==self.ctr:
self.delete_end()
else:
temp=self.head
i=0
while i<pos:
temp=temp.next
i+=1
print("node deleted",temp.data)
temp.prev.next=temp.next
temp.next.prev=temp.prev
temp.next=None
temp.preve=None
self.ctr -=1
return
def traverse_f(self):
if self.head==None:
print("No nodes exist")
temp=self.head
i=0
while i<self.ctr:
print(temp.data)
temp=temp.next
i+=1
return
def traverse_r(self):
if self.head==None:
print("No nodes exist")
temp=self.head
while temp.next is not None:
temp=temp.next
while temp is not None:
print(temp.data)
temp=temp.prev
def menu():
print("1.Insert at beginning")
print("2.Insert at position")
print("3.Insert at end")
print("4.Delete at beginning")
print("5.Delete at position")
print("6.Delete at end")
print("7.Count no of nodes")
print("8.Traverse forward")
print("9.Traverse reverse")
print("10.Quit")
ch=eval(input("Enter choice:"))
return ch
a. To write a Python program to implement Stack and its operations using list.
b. To write a Python program to implement Queue and its operations using list.
Procedure for Stack using List
1. STACK: Stack is a linear data structure which works under the principle of last in first out.
Basic operations: push, pop, display.
2. PUSH: if (top==MAX), display Stack overflow. Otherwise reading the data and making stack
[top] =data and incrementing the top value by doing top++.
3. Pop: if (top==0), display Stack underflow. Otherwise printing the element at the top of the
stack and decrementing the top value by doing the top.
4. DISPLAY: If (top==0), display Stack is empty. Otherwise printing the elements in the stack
from stack [0] to stack [top].
1. QUEUE: Queue is a linear data structure which works under the principle of first in first out.
Basic operations: Insertion, deletion, display.
2. Inserion: if (rear==MAX), display Queue is full. Else reading data and inserting at queue [rear],
and doing rear++.
3. Deletion: if (front==rear), display Queue is empty .Else printing element at queue [front] and
doing front++.
4. Display: if (front==rear) ,display No elements in the queue .Else printing the elements from
queue[front] to queue[rear].
Example: Consider a stack with 5 elements capacity. When an element is added to a stack, the
operation is performed by Push().
When an element is taken off from the stack, the operation is performed by Pop().
Program for implementing Stack using list
top=0
mymax=eval(input("Enter Maximum size of stack:"))
def createStack():
stack=[]
return stack
def isEmpty(stack):
return len(stack)==0
def Push(stack,item):
stack.append(item)
print("Pushed to stack",item)
def Pop(stack):
if isEmpty(stack):
return "stack underflow"
return stack.pop()
stack=createStack()
while True:
print("1.Push")
print("2.Pop")
print("3.Display")
print("4.Quit")
ch=int(input("Enter your choice:"))
if ch==1:
if top<mymax:
item=input("Enter any elements:")
Push(stack,item)
top+=1
else:
print("Stack overflow")
elif ch==2:
print(Pop(stack))
elif ch==3:
print(stack)
else:
print("Exit")
break
Output:
Program for implementing Linear Queue using list
front=0
rear=0
mymax=eval(input("Enter maximum size of queue:"))
def createQueue():
queue=[]
return queue
def isEmpty(queue):
return len(queue)==0
def enqueue(queue,item):
queue.append(item)
print("Enqueued to queue",item)
def dequeue(queue):
if isEmpty(queue):
return "Queue is empty"
item=queue[0]
del queue[0]
return item
queue=createQueue()
while True:
print("1.Enqueue")
print("2.Dequeue")
print("3.Display")
print("4.Quit")
ch=int(input("Enter your choice:"))
if ch==1:
if rear<mymax:
item=input("Enter any elements:")
enqueue(queue,item)
rear+=1
else:
print("Queue is full")
elif ch==2:
print(dequeue(queue))
elif ch==3:
print(queue)
else:
print("Exit")
break
Output:
RESULT:
Thus the above program to implement stack and queue are executed and verified.
WEEK-3
IMPLEMENTATION OF STACK USING LINKED LIST
OBJECTIVE:
To write a Python script to implement stack using linked list.
PROGRAM LOGIC:
1. STACK: Stack is a linear data structure which works under the principle of last in first out.
Basic operations: push, pop, display.
2. PUSH: if (newnode==NULL), display Stack overflow. if(start == NULL) then start = newnode.
Otherwise use loop and copy address of new node in to old node by creating link.
3. Pop: if (top == NULL), display Stack underflow. Otherwise printing the element at the top of
the stack and decrementing the top value by doing the top.
4. DISPLAY: if (top == NULL), display Stack is empty. Otherwise printing the elements in the
stack from top.
SOURCE CODE:class
Node:
def init (self,data):
self.data=data
self.next=None
class Stack:
def init (self):
self.head=None
self.ctr=0
self.top=None
def Push(self,data):
node=Node(data)
if self.head==None:
self.head=node
self.top=node
else:
self.top.next=node
self.top=node
print("Node pushed to stack",data)
self.ctr+=1
return
def Pop(self):
if self.head==None:
print("Stack Underflow")
elif self.head==self.top:
print("Deleted from Stack",self.head.data)
self.head=self.top=None
self.ctr-=1
else:
print("Deleted from Stack",self.top.data)
temp=self.head
while temp.next is not self.top:
temp=temp.next
temp.next=None
self.top=temp
self.ctr-=1
return
def Traverse(self):
if self.head==None:
print("No Nodes exist")
return
temp=self.head
while temp is not None:
print(temp.data)
temp=temp.next
def Menu():
print("1.Push\n2.Pop\n3.Traverse\n4.Number of nodes\n5.Exit")
ch=int(input("Enter choice:"))
return ch
s=Stack()
print("**************Stack*****************")
while True:
ch=Menu()
if ch==1:
data=input("Enter data:")
s.Push(data)
elif ch==2:
s.Pop()
elif ch==3:
s.Traverse()
elif ch==4:
print("Number of nodes",s.ctr)
else:
print('Quit')
break
Output:
RESULT:
Thus the above programs are implemented and verified.
WEEK 3
IMPLEMENTATION OF QUEUE USING LINKED LIST
OBJECTIVE:
PROGRAM LOGIC:
1. QUEUE: Queue is a linear data structure which works under the principle of first in first out.
Basic operations: Insertion, deletion, display.
2. Inserion: if newnode ==NULL, display Queue is full. Else reading data and inserting at queue
rear.
3. Deletion: if (front==NULL), display Queue is empty .Else printing element at queue front
4. Display: if (front==NULL) ,display No elements in the queue .Else printing the elements from
front to rear.
SOURCE CODE:
class Node:
def init (self,data):
self.data=data
self.next=None
class Queue:
def init (self):
self.front=None
self.ctr=0
self.rear=None
def Enqueue(self,data):
node=Node(data)
if self.front==None:
self.front=node
self.rear=node
else:
self.rear.next=node
self.rear=node
print("Node enqueued to queue",data)
self.ctr+=1
return
def Dequeue(self):
if self.front==None:
print("No Nodes exist")
else:
print("Dequeued from queue",self.front.data)
self.front=self.front.next
self.ctr-=1
return
def Traverse(self):
if self.front==None:
print("No Nodes exist")
return
temp=self.front
while temp is not None:
print(temp.data)
temp=temp.next
def Menu():
print("1.Enqueue\n2.Dequeue\n3.Traverse\n4.Number of nodes\n5.Exit")
ch=int(input("Enter choice:"))
return ch
print("*******************Queue*************")
s=Queue()
while True:
ch=Menu()
if ch==1:
data=input("Enter data:")
s.Enqueue(data)
elif ch==2:
s.Dequeue()
elif ch==3:
s.Traverse()
elif ch==4:
print("Number of nodes",s.ctr)
else:
print('Quit')
break
10.1 INPUT/OUTPUT:-
RESULT:
a. To write a Python program to convert infix expression into postfix expression using stack.
b. To write a Python program to evaluate the postfix expression using stack.
PROGRAM LOGIC:
1. Read an infix expression and scan the symbols from left to right.
2. If the symbol is an operand, then write down in the postfix string.
3. If the symbol is a left parenthesis, then push it onto stack.
4. If the symbol is a right parenthesis, then pop the operators from until it find a left parenthesis or
the stack is empty.
5. If the symbol is an operator, then check it's priority with the top most operator in the stack.
6. If the incoming operator is having high priority then the top most operator in the stack, then push
the new operator onto stack, otherwise pop the existing operator and push the new operator.
7. Display the content of the postfix string.
1. Read a postfix expression and scan the symbols from left to right.
2. If the symbol is an operand, then push it onto the stack.
3. If the symbol is an operator, the pop the top most two symbols and apply the operator.
4. Then push the result again in to stack.
5. Display the final result which is in stack.
Program to convert Infix Expression Into Postfix Expression
class Stack:
def init (self):
self.items = []
def isEmpty(self):
return self.items == []
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
def infix_postfix(infixexp):
prec={}
prec["^"]=4
prec["*"]=3
prec["/"]=3
prec["+"]=2
prec["-"]=2
prec["("]=1
opStack=Stack()
postfixList=[]
tokenList=infixexp.split()
for token in tokenList:
if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or \
token in "abcdefghijklmnopqrstuvwxyz" or token in "0123456789":
postfixList.append(token)
elif token == '(':
opStack.push(token)
elif token == ')':
topToken = opStack.pop()
while topToken != '(':
postfixList.append(topToken)
topToken=opStack.pop()
else:
while (not opStack.isEmpty()) and \
(prec[opStack.peek()]>=prec[token]):
postfixList.append(opStack.pop())
opStack.push(token)
while not opStack.isEmpty():
postfixList.append(opStack.pop())
return " ".join(postfixList)
a=infix_postfix('A + B * C - D / E * H')
print("The postfix expression of infix expression A + B * C - D / E * H is \n",a)
Output:
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)
def postfix_eval(s):
s=s.split()
n=len(s)
stack =[]
for i in range(n):
if s[i].isdigit():
#append function is equivalent to push
stack.append(int(s[i]))
elif s[i]=="+":
a=stack.pop()
b=stack.pop()
stack.append(int(a)+int(b))
elif s[i]=="*":
a=stack.pop()
b=stack.pop()
stack.append(int(a)*int(b))
elif s[i]=="/":
a=stack.pop()
b=stack.pop()
stack.append(int(b)/int(a))
elif s[i]=="-":
a=stack.pop()
b=stack.pop()
stack.append(int(b)-int(a))
return stack.pop()
def doMath(op,op1,op2):
if op == "^":
return op1 ^ op2
elif op == "*":
return op1 * op2
elif op == "/":
return op1 / op2
elif op == "//":
return op1 // op2
elif op == "+":
return op1 + op2
else:
return op1 - op2
s=input("enter string:")
val=postfix_eval(s)
print("The value of postfix expression",s,"is",val)
Output:
RESULT:
Thus the above program to implement stack and queue are executed and verified.
WEEK-5
AIM:
To write a Python program to implement binary search tree creation, traversal and count node.
PROGRAM LOGIC:
1. The left sub tree of a node contains smaller nodes than a root node.
2. The right sub tree of a node contains greater nodes than a root node.
3. Both the left and right sub trees must also be binary search trees.
4. There are three types of tree traversals: Preorder, Postorder, and Inorder.
Pre-order traversal
Algorithm:
1. Visit the root (we will print it when we visit to show the order of visiting)
2. Traverse the left subtree in pre-order
3. Traverse the right subtree in pre-order
In-order traversal
Visit the root node in between the left and right node (in)
Algorithm:
1. Traverse the left subtree in in-order
2. Visit the root (we will print it when we visit to show the order of visiting)
3. Traverse the right subtree in in-order
Post-order traversal
Visit the root node after (post) visiting the left and right subtree.
Algorithm:
1. Traverse the left subtree in in-order
2. Traverse the right subtree in in-order
3. Visit the root (we will print it when we visit to show the order of visiting)
Algorithm:
maxDepth()
1. If tree is empty then return 0
2. Else
a. Get the max depth of left subtree recursively i.e., call
maxDepth( tree->left-subtree)
b. Get the max depth of right subtree recursively i.e., call
maxDepth( tree->right-subtree)
c. Get the max of max depths of left and rightsubtrees and add 1
to it for the current node. max_depth = max(max dept of left
subtree,
max depth of right subtree)
+1
(c) Return max_depth
Algorithm
getLeafCount(node)
1) If node is NULL then return 0.
2) Else If left and right child nodes are NULL return 1.
3) Else recursively calculate leaf count of the tree using below formula.
Leaf count of a tree=Leaf count of left sub tree + leaf count of right sub tree
SOURCE CODE:
class Node:
class searchtree:
def init (self): #constructor of class
self.root = None
def create(self,val): #create binary search tree nodes
if self.root == None:
self.root = Node(val)
else:
current = self.root
while 1:
if val < current.info:
if current.left:
current = current.left
else:
current.left = Node(val)
break;
elif val > current.info:
if current.right:
current = current.right
else:
current.right = Node(val)
break;
else:
break
tree = searchtree()
arr = [8,3,1,6,4,7,10,14,13]
for i in arr:
tree.create(i)
print ('Breadth-First Traversal')
tree.bft()
print ('Inorder Traversal')
tree.inorder(tree.root)
print ('Preorder Traversal')
tree.preorder(tree.root)
print ('Postorder Traversal')
tree.postorder(tree.root)
Output:
Breadth-First Traversal
8
3 10
1 6 14
4 7 13
Inorder Traversal
1
3
4
6
7
8
10
13
14
Preorder Traversal
8
3
1
6
4
7
10
14
13
Postorder Traversal
1
4
7
6
3
13
14
10
8
class BinaryTree:
def init (self, data):
self.data = data
self.left = None
self.right = None
def insert_left(self, new_data):
if self.left == None:
self.left = BinaryTree(new_data)
else:
t = BinaryTree(new_data)
t.left = self.left
self.left = t
def insert_right(self, new_data):
if self.right == None:
self.right = BinaryTree(new_data)
else:
t = BinaryTree(new_data)
t.right = self.right
self.right = t
def get_left(self):
return self.left
def get_right(self):
return self.right
def set_data(self, data):
self.data = data
def get_data(self):
return self.data
def size(my_tree):
if not my_tree:
return 0
return 1 + size(my_tree.get_left()) + size(my_tree.get_right())
a = BinaryTree(1)
a.insert_left(2)
a.insert_right(3)
print(size(a))
Output:
No of nodes: 3
RESULT:
Thus the above programs are implemented and verified.
IMPLEMENTATION OF BINARY HEAPS
AIM:
To write a Python program to implement binary search tree creation, traversal and count node.
PROGRAM LOGIC:
In a Max heap, the value of the root node will be greater than the values of its child nodes. Hence, the
root node will have the highest value in the whole tree.
1. Heapify:
Given a binary tree, converting it into a heap is called "Heapify". We use the array implementation of the
tree, and we'll convert it into an array representing a heap:
#Min Heap
def heapify(BT, nodes, node):
smallest = node
leftchild = 2 * node + 1
rightchild = 2 * node + 2
if smallest != node:
BT[node], BT[smallest] = BT[smallest], BT[node]
heapify(BT, nodes, smallest)
BinaryTree = [7, 2, 5, 6, 3, 4, 1]
for i in range((len(BinaryTree)//2)-1, -1, -1):
heapify(BinaryTree, len(BinaryTree), i)
print(BinaryTree)
Output:
[1, 2, 4, 6, 3, 7, 5]
As you can observe, the minimum node 1 is kept at the root(index-0) position, satisfying the minheap
property.
2. Inserting a node
Given a node, we need to append the node to the array at the end such that the last node from left to right is
getting filled, and the most important step is to heapify the array after insertion:
BinaryTree = [2, 4, 6, 3, 7, 5]
for i in range((len(BinaryTree)//2)-1, -1, -1):
heapify(BinaryTree, len(BinaryTree), i)
print(BinaryTree)
insertion(BinaryTree, 1)
print(BinaryTree)
Output:
[2, 3, 4, 6, 7, 5]
[1, 3, 2, 6, 7, 5, 4]
We inserted 1 into the heap. Among all the elements in a heap, 1 is the smallest; according to the minheap's
property, it must be placed at the root(index-0).
If the node we want to delete from the heap is a leaf node, we can delete it. If it is an internal node, we need
to swap the node with any leaf node and then delete it.
BinaryTree = [7, 2, 5, 6, 3, 4]
for i in range((len(BinaryTree)//2)-1, -1, -1):
heapify(BinaryTree, len(BinaryTree), i)
print(BinaryTree)
insertion(BinaryTree, 1)
print(BinaryTree)
deletion(BinaryTree, 1)
print(BinaryTree)
Output:
[2, 3, 4, 6, 7, 5]
[1, 3, 2, 6, 7, 5, 4]
[2, 3, 4, 6, 7, 5]
In a minheap, the root node will have the minimum value. Hence, we can write a function to find the min
node and return the root(index-0).
In the same way, in a maxheap, the root node will have the maximum value:
def minnode(BT):
return BT[0]
print(minnode([3, 7, 8, 9]))
Output:
RESULT:
Thus the above programs are implemented and verified.
WEEK-6
GRAPH TRAVERSAL TECHNIQUES
AIM:
PROGRAM LOGIC:
SOURCE CODE:
class Graph:
# Constructor
def init (self):
self.graph = defaultdict(list)
def addEdge(self,u,v):
self.graph[u].append(v)
def DFSUtil(self,v,visited):
visited[v]= True
print (v),
for i in self.graph[v]:
if visited[i] == False:
self.DFSUtil(i, visited)
def DFS(self,v):
visited = [False]*(len(self.graph))
self.DFSUtil(v,visited)
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)
class Graph:
def init (self):
self.graph = defaultdict(list)
def addEdge(self,u,v):
self.graph[u].append(v)
visited = [False]*(len(self.graph))
queue = []
queue.append(s)
visited[s] = True
while queue:
s = queue.pop(0)
print (s)
for i in self.graph[s]:
if visited[i] == False:
queue.append(i)
visited[i] = True
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)
g= Graph(6)
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
Output:
RESULT:
AIM:
class Graph():
self.V = vertices
min = 1e7
for v in range(self.V):
min = dist[v]
min_index = v
return min_index
dist[src] = 0
u = self.minDistance(dist, sptSet)
sptSet[u] = True
for v in range(self.V):
self.printSolution(dist)
g = Graph(9)
[0, 8, 0, 7, 0, 4, 0, 0, 2],
[0, 0, 0, 0, 0, 2, 0, 1, 6],
[0, 0, 2, 0, 0, 0, 6, 7, 0]
g.dijkstra(0)
Output:
0 0
1 4
2 12
3 19
4 21
5 11
6 9
7 8
8 14
Program To Implement Bellman ford Algorithm
distances[source] = 0
for u in graph:
for u in graph:
return distances
graph = {
'C': {},
source = 'A'
print(shortest_distances)
Output:
RESULT:
AIM:
def prims_algorithm(self):
in_mst = [False] * self.size
key_values = [float('inf')] * self.size
parents = [-1] * self.size
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
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
output:
RESULT:
Thus the above programs are implemented and verified.
PROGRAM TO IMPLEMENT PRIM’S ALGORITHM
class Graph:
def __init__(self, vertices):
self.vertices = vertices
self.edges = []
self.adjacency_list = {v: [] for v in vertices}
def kruskal(self):
minimum_spanning_tree = set()
parent = {}
rank = {}
for v in self.vertices:
parent[v] = v
rank[v] = 0
sorted_edges = sorted(self.edges, key=lambda x: x[2])
for edge in sorted_edges:
u, v, weight = edge
root_u = self.find_parent(parent, u)
root_v = self.find_parent(parent, v)
if root_u != root_v:
minimum_spanning_tree.add(edge)
self.union(parent, rank, root_u, root_v)
return minimum_spanning_tree
vertices = [0, 1, 2, 3]
g = Graph(vertices)
g.add_edge(0, 1, 5)
g.add_edge(0, 2, 10)
g.add_edge(0, 3, 3)
g.add_edge(1, 3, 1)
g.add_edge(2, 3, 4)
minimum_spanning_tree = g.kruskal()
print(minimum_spanning_tree)
OUTPUT:
RESULT:
Thus the above programs are implemented and verified.
WEEK- 9
SEARCHING TECHNIQUES
AIM:
Example: Given a list of n elements and search a given element x in the list using linear search.
a. Start from the leftmost element of list a[] and one by one compare x with each element of
list a[].
b. If x matches with an element, return the index.
c. If x doesn’t match with any of elements, return -1.
Example: Given a sorted list of a[] of n elements, search a given element x in list.
a. Search a sorted list by repeatedly dividing the search interval in half. Begin with an interval
covering the whole list.
b. If the search key is less than the item in the middle item, then narrow the interval to the
lower half. Otherwise narrow it to the upper half.
c. Repeat the procedure until the value is found or the interval is empty.
Consider a sorted list a[] with 9 elements and the search key is 31.
0 1 2 3 4 5 6 7 8
11 23 31 33 65 68 71 89 100
SOURCE CODE:
def l_search(a,x,l,n):
if l<n:
if a[l]==x:
print("The element found at",l+1,"position")
else:
l_search(a,x,l+1,n)
else:
print("Element not found")
print("Enter list:")
a=[int(b) for b in input().split()]
x=eval(input("Enter the search element:"))
n=len(a)
l_search(a,x,0,n)
Output:
def b_search(a,x,l,n):
if l<=n:
mid=(l+n)//2
if a[mid]==x:
print("The element found at",mid+1,"position")
else:
if a[mid]>x:
b_search(a,x,l,mid-1)
else:
b_search(a,x,mid+1,n)
else:
print("Element not found")print("Enter list:")
a=[int(b) for b in
input().split()]list.sort(a)
Output:
RESULT:
Thus the above program to implement searching algorithms like linear search and binary search are
executed and verified.
WEEK –10
SORTING TECHNIQUES
AIM:
a. To write Python script for implementing Bubble sort techniques to arrange a list of integers
inascending order.
b. To write Python script for implementing insertion sort techniques to arrange a list of integers in
ascending order.
c. To write Python script for implementing selection sort techniques to arrange a list of integers
inascending order.
d. To write Python script for implementing Radix sort techniques to arrange a list of integers in
ascending order.
e. To write Python script for implementing Bucket sort techniques to arrange a list of integers
inascending order
PROGRAM LOGIC:
Example: Bubble Sort is the simplest sorting algorithm that works by repeatedly swapping the
adjacent elements if they are not in order.
First Pass
5 1 4 2 8 Compare the first two elements, and swaps since 5 > 1
1 5 4 2 8 Compare 5 and 4 and swap since 5 > 4
1 4 5 2 8 Compare 5 and 2 and swap since 5 > 2
1 4 2 5 8 Compare 5 and 8 and since 5 < 8, no swap.
Second Pass
1 4 2 5 8 Compare the first two elements, and as 1 < 4, no
swap.
1 4 2 5 8 Compare 4 and 2, swap since 4 > 2
1 2 4 5 8 Compare 4 and 5, no swap.
1 2 4 5 8 Compare 5 and 8 and no swap.
Third Pass
1 2 4 5 8 Compare the first two elements and no swap.
1 2 4 5 8 Compare 2 and 4, no swap.
1 2 4 5 8 Compare 4 and 5, no swap.
1 2 4 5 8 Compare 5 and 8, no swap.
Fourth Pass
1 2 4 5 8 Compare the first two elements and no swap.
1 2 4 5 8 Compare 2 and 4, no swap.
1 2 4 5 8 Compare 4 and 5, no swap.
1 2 4 5 8 Compare 5 and 8, no swap.
Example: This is an in-place comparison-based sorting algorithm. Here, a sub-list is maintained which is
always sorted. An element which is to be inserted in this sorted sub-list, has to find its appropriate place and
then it has to be inserted. Consider an unsorted list with 8 elements.
Index 0 1 2 3 4 Remarks
List 64 25 12 22 11 Find the minimum element in a[0 .. 4] and place it
at beginning.
Iteration 1 11 25 12 22 64 Find the minimum element in a[1 .. 4] and place it
at beginning of a[1 .. 4]
Iteration 2 11 12 25 22 64 Find the minimum element in a[2 .. 4] and place it
at beginning of a[2 .. 4]
Iteration 3 11 12 22 25 64 Find the minimum element in a[3 .. 4] and place it
at beginning of a[3 .. 4]
Iteration 4 11 12 22 25 64 Finally the list is sorted.
def b_sort(a):
n = len(a)
for i in range(n):
for j in range(0, n-i-1):
if a[j] > a[j+1] :
a[j], a[j+1] = a[j+1], a[j]
def i_sort(a):
for i in range(1,len(a)):
temp=a[i]
pos=i
while pos>0 and a[pos-1]>temp:
a[pos]=a[pos-1]
pos-=1
a[pos]=temp
def s_sort(a):
for i in range(len(a)):
least=i
for k in range(i+1,len(a)):
if a[k]<a[least]:
least=k
swap(a,least,i)
def swap(a,least,i):
temp=a[least]
a[least]=a[i]
a[i]=temp
n = len(arr)
for i in range(1,10):
count[i] += count[i-1]
i = n-1
while i>=0:
index = (arr[i]/exp1)
output[ count[ int((index)%10) ] - 1] = arr[i]
count[int((index)%10)] -= 1
i -= 1
i=0
for i in range(0,len(arr)):
arr[i] = output[i]
def radixSort(arr):
max1 = max(arr)
exp = 1
while max1 // exp > 0:
countingSort(arr,exp)
exp *= 10
arr = [ 170, 45, 75, 90, 802, 24, 2, 66]
radixSort(arr)
for i in range(len(arr)):
print(arr[i],end=" ")
Output
2 24 45 66 75 90 170 802
def bucketSort(array):
bucket = []
for i in range(len(array)):
bucket.append([])
for j in array:
index_b = int(10 * j)
bucket[index_b].append(j)
for i in range(len(array)):
bucket[i] = sorted(bucket[i])
k=0
for i in range(len(array)):
for j in range(len(bucket[i])):
array[k] = bucket[i][j]
k += 1
return array
array = [.42, .32, .33, .52, .37, .47, .51]
print("Sorted Array in descending order is")
print(bucketSort(array))
Output:
Sorted Array in descending order is
[0.32, 0.33, 0.37, 0.42, 0.47, 0.51, 0.52]
RESULT:
Thus the above program to implement sorting algorithms are executed and verified.
WEEK- 11
SORTING TECHNIQUES
AIM:
1. To write Python programs for implementing Quick sort technique to arrange a list of integers
inascending order.
2. To write Python programs for implementing merge sort technique to arrange a list of integers
inascending order.
3. To write Python programs for implementing heap sort technique to arrange a list of integers in
ascending order.
4. To write Python programs for implementing shell sort technique to arrange a list of integers in
ascending order.
Algorithm Partition(a, m, p)
// within a[m], a[m+1], ………, a[p-1] the elements are rearranged in such a manner that if initially
// t = a[m], then after completion a[q] = t for some q between m and p-1, a[k] <= t for m<=k<=q,
// and a[k]>=t for q<k<p. q is returned, set a[p] = ∞
{
v := a[m]; i:=m; j:=p;
repeat
{
repeat
i:= i+1;
until (a[i] >=v);
repeat
j:=j-1
until (a[j]<=v);
if( i<j) then interchange(a, i, j);
}until(i>=j);
a[m]:= a[j]; a[j]=v; return j;
}
Algorithm Interchange(a, i, j)
//exchange a[i] and a[j]
{
p:=a[i];
a[i]:=a[j];
a[j]:=p;
}
Example: Quick sort is a divide and conquer algorithm. Quick sort first divides a large list into two smaller
sub-lists: the low elements and the high elements. Quick sort can then recursively sort the sub-lists.
Step-by-step example:
0 1 2 3 4 5 6 7 8 9 10 11 12 Remarks
38 08 16 06 79 57 24 56 02 58 04 70 45
Pivot Up Down Swap up
and down
38 08 16 06 04 57 24 56 02 58 79 70 45
Pivot Up Down Swap up
and down
38 08 16 06 04 02 24 56 57 58 79 70 45
Pivot Down Up Swap Pivot
and down
24 08 16 06 04 02 38 56 57 58 79 70 45
Pivot Down Up Swap Pivot
and down
02 08 16 06 04 24 38
Pivot Up Swap Pivot
Down and down
02 08 16 06 04 24 38
Pivot Up Down Swap up
and down
02 08 04 06 16 24 38
Pivot Down Up Swap Pivot
and down
02 06 04 08 16 24 38
Pivot Down Up Swap Pivot
and down
02 04 06 08 16 24 38 Left sub-list
is sorted
Repeat the similar procedure for right sub-list also
if (h>mid) then
for k:=j to high do
{
b[i]:= a[k]; i:= i+1;
}
else
for k:=h to mid do
{
b[i]:= a[k]; i:= i+1;
}
for k:= low to high do a[k] = b[k]
}
Example: This is a divide and conquer algorithm. Merge sort works as follows :
1. Divide the input which we have to sort into two parts in the middle. Call it the left part and right
part.
2. Sort each of them separately by using the same function recursively.
3. Then merge the two sorted parts.
def q_sort(a,low,high):
if low<high:
pivotpos=partition(a,low,high)
q_sort(a,low,pivotpos-1)
q_sort(a,pivotpos+1,high)
def partition(a,low,high):
pivotvalue=a[low]
up=low+1
down=high
done=False
while not done:
while up<=down and a[up]<=pivotvalue:
up+=1
while down>=up and a[down]>=pivotvalue:
down-=1
if down<up:
done=True
else:
temp=a[up]
a[up]=a[down]
a[down]=temp
temp=a[low]
a[low]=a[down]
a[down]=temp
return down
Output:
Program for implementing Merge Sort
def m_sort(a):
for i in range(len(a)):
if i>1:
mid=len(a)//2
l_half=a[:mid]
r_half=a[mid:]
m_sort(l_half)
m_sort(r_half)
i=j=k=0
while i<len(l_half) and j<len(r_half):
if l_half[i]<r_half[j]:
a[k]=l_half[i]
i+=1
else:
a[k]=r_half[j]
j+=1
k+=1
while i<len(l_half):
a[k]=l_half[i]
i+=1
k+=1
while j<len(r_half):
a[k]=r_half[j]
j+=1
k+=1
print("Enter elements into list:")
a=[int(x) for x in input().split()]
m_sort(a)
print("The sorted list is",a)
Output:
# Change root
if largest != b:
array[b], array[largest] = array[largest], array[b]
heapify(array, a, largest)
# maxheap..
for b in range(a // 2 - 1, -1, -1):
heapify(array, a, b)
# extract elements
for b in range(a-1, 0, -1):
array[b], array[0] = array[0], array[b] # swap
heapify(array, b, 0)
# Driver code
array = [ 7, 2, 5, 6, 3, 1, 8, 4]
print("The original array is: ", array)
Heap_Sort(array)
a = len(array)
print ("Array after sorting is: ", array)
output:
The original array is: [7, 2, 5, 6, 3, 1, 8, 4]
Array after sorting is: [1, 2, 3, 4, 5, 6, 7, 8]
array[j] = temp
interval //= 2
data = [9, 8, 3, 7, 5, 6, 4, 1]
size = len(data)
shellSort(data, size)
print('Sorted Array in Ascending Order:')
print(data)
print ("Array after sorting is: ", array)
output:
Sorted Array in Ascending Order:
[1, 3, 4, 5, 6, 7, 8, 9]
RESULT:
Thus the above program to implement sorting algorithms are executed and verified.
WEEK-12
PROGRAM:
class HashTable:
def __init__(self, size):
self.size = size
self.table = [[] for _ in range(size)]
def display(self):
for i, chain in enumerate(self.table):
print(f"Index {i}: {chain}")
# Example usage
if __name__ == "__main__":
ht = HashTable(10) # Create a hash table of size 10
# Insert some key-value pairs
ht.insert("apple", 10)
ht.insert("banana", 20)
ht.insert("grape", 30)
ht.insert("cherry", 40)
ht.insert("melon", 50)
# Display the hash table
ht.display()
# Search for some keys
print("Search for 'apple':", ht.search("apple"))
print("Search for 'banana':", ht.search("banana"))
print("Search for 'mango':", ht.search("mango")) # This should return None
# Delete some keys
ht.delete("banana")
ht.delete("grape")
# Display the hash table after deletion
ht.display()
OUTPUT:
Index 0: []
Index 1: []
Index 2: []
Index 3: []
Index 4: [('apple', 10), ('grape', 30)]
Index 5: []
Index 6: [('melon', 50)]
Index 7: []
Index 8: []
Index 9: [('banana', 20), ('cherry', 40)]
Index 0: []
Index 1: []
Index 2: []
Index 3: []
Index 4: [('apple', 10)]
Index 5: []
Index 6: [('melon', 50)]
Index 7: []
Index 8: []
Index 9: [('cherry', 40)]
RESULT:
Thus the above programs are implemented and verified.