ADS LAB
ADS LAB
Insertion in Binary Search Tree (BST):-A new key is always inserted at the leaf by
maintaining the property of the binary search tree. We start searching for a key from the root
until we hit a leaf node. Once a leaf node is found, the new node is added as a child of the
leaf node. The below steps are followed while we try to insert a node into a binary search
tree:
Check the value to be inserted (X) with the value of the current node (Y) we are at
If X is less than val move to the left subtree.
Otherwise, move to the right subtree.
Once the leaf node is reached, insert X to its right or left based on the relation
between X and the leaf node’s value.
ALGORITHM
Step 2: END
Inorder Traversal
The inorder traversal operation in a Binary Search Tree visits all its nodes in the following
order −
Firstly, we traverse the left child of the root node/current node, if any.
Next, traverse the current node.
Lastly, traverse the right child of the current node, if any.
Algorithm
1. START
2. Traverse the left subtree, recursively
3. Then, traverse the root node
4. Traverse the right subtree, recursively.
5. END
Preorder Traversal
The preorder traversal operation in a Binary Search Tree visits all its nodes. However, the root node
in it is first printed, followed by its left subtree and then its right subtree.
Algorithm
1. START
2. Traverse the root node first.
3. Then traverse the left subtree, recursively
4. Later, traverse the right subtree, recursively.
5. END
Postorder Traversal
Like the other traversals, postorder traversal also visits all the nodes in a Binary Search Tree and
displays them. However, the left subtree is printed first, followed by the right subtree and lastly, the
root node.
Algorithm
1. START
2. Traverse the left subtree, recursively
3. Traverse the right subtree, recursively.
4. Then, traverse the root node
5. END
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-2
Objective: Program for Searching in Binary Search Tree
Searching means finding or locating some specific element or node within a data structure.
However, searching for some specific node in binary search tree is pretty easy due to the fact
that, element in BST are stored in a particular order.
1. Compare the element with the root of the tree.
2. If the item is matched then return the location of the node.
3. Otherwise check if item is less than the element present on root, if so then move to the
left sub-tree.
4. If not, then move to the right sub-tree.
5. Repeat this procedure recursively until match found.
6. If element is not found then return NULL.
Algorithm:
Search (ROOT, ITEM)
Step 1: IF ROOT -> DATA = ITEM OR ROOT = NULL
Return ROOT
ELSE
IF ROOT < ROOT -> DATA
Return search(ROOT -> LEFT, ITEM)
ELSE
Return search(ROOT -> RIGHT,ITEM)
[END OF IF]
[END OF IF]
Step 2: END
IMPLENENTATION
OUTPUT
LAB PRACTICAL-3
Objective: Program for Deletion in Binary Search Tree
Delete function is used to delete the specified node from a binary search tree. However, we
must delete a node from a binary search tree in such a way, that the property of binary search
tree doesn't violate. There are three situations of deleting a node from binary search tree.
1. The node to be deleted is a leaf node: It is the simplest case, in this case, replace the leaf
node with the NULL and simple free the allocated space.
2. The node to be deleted has only one child: In this case, replace the node with its child
and delete the child node, which now contains the value which is to be deleted. Simply
replace it with the NULL and free the allocated space.
3. The node to be deleted has two children: It is a bit complexed case compare to other two
cases. However, the node which is to be deleted, is replaced with its in-order successor or
predecessor recursively until the node value (to be deleted) is placed on the leaf of the tree.
After the procedure, replace the node with NULL and free the allocated space.
ALGORITHM
Delete (TREE, ITEM)
Step 2: END
IMPLEMENTATION
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
# Base case
if root is None:
return root
else:
# If root matches with the given key
# Driver code
if __name__ == "__main__":
root = Node(10)
root.left = Node(5)
root.right = Node(15)
root.right.left = Node(12)
root.right.right = Node(18)
x = 15
root = del_node(root, x)
inorder(root)
print()
OUTPUT
LAB PRACTICAL-4
Objective: Program for Insertion in AVL Tree.
Theory:-The AVL TREE is a height-balanced binary search tree which means it is also a
binary tree that is balanced by the left and right subtree of a node. The tree is said to be
balanced when the balance factor of each node is either -1, 0, or +1.
The Balance factor of a tree can be defined as:
Balanced Factor(X) = height(left Subtree (X)) – height(right Subtree(X))
Example of AVL Tree:-
Update Heights:
After the insertion, update the height of the ancestor nodes.
Occurs when a node is inserted into the left subtree of the left child of the unbalanced node.
Perform a Right Rotation on the unbalanced node.
Occurs when a node is inserted into the right subtree of the right child of the unbalanced
node. Perform a Left Rotation on the unbalanced node.
Occurs when a node is inserted into the right subtree of the left child of the unbalanced
node. Perform a Left Rotation on the left child, followed by a Right Rotation on the
unbalanced node.
Steps:
1. Perform a Left Rotation on the left child of the unbalanced node to convert it into a
Left-Left case.
2. Perform a Right Rotation on the unbalanced node.
Occurs when a node is inserted into the left subtree of the right child of the unbalanced node.
Perform a Right Rotation on the right child, followed by a Left Rotation on the unbalanced node.
Steps:
1. Perform a Right Rotation on the right child of the unbalanced node to convert it into
a Right-Right case.
2. Perform a Left Rotation on the unbalanced node.
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-5
Objective: Program for Searching in AVL Tree
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-5
Objective: Program for Deletion in Binary Search Tree
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-7
Objective: Program for Insertion in Skip List
A skip list is a probabilistic data structure. The skip list is used to store a sorted list of
elements or data with a linked list. It allows the process of the elements or data to view
efficiently.
The skip list is an extended version of the linked list. It allows the user to search, remove, and
insert the element very quickly. It consists of a base list that includes a set of elements which
maintains the link hierarchy of the subsequent elements.
It is built in two layers: The lowest layer and Top layer.
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-8
Objective: Program for Searching in Skip List
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-9
Objective: Program for Deletion in Skip List
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-10
Objective: Program for Naïve String Matching Algorithm
The naive approach tests all the possible placement of Pattern P [1.......m] relative to text T
[1......n]. We try shift s = 0, 1.......n-m, successively and for each shift s. Compare T
[s+1.......s+m] to P [1......m].
The naive algorithm finds all valid shifts using a loop that checks the condition P [1.......m] =
T [s+1.......s+m] for each of the n - m +1 possible value of s.
ALGORITHM
NAIVE-STRING-MATCHER (T, P)
1. n ← length [T]
2. m ← length [P]
3. for s ← 0 to n -m
4. do if P [1.....m] = T [s + 1....s + m]
5. then print "Pattern occurs with shift" s
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-11
Objective: Program for Rabin Karp String Matching Algorithm
In the Naive string matching algorithm, we check whether every substring of the text of
the pattern’s size is equal to the pattern or not one by one.
The Rabin-Karp algorithm also check every substring. But unlike the Naive algorithm, the
Rabin Karp algorithm matches the hash value of the pattern with the hash value of the
current substring of text, and if the hash values match then only it starts matching individual
characters. So Rabin Karp algorithm needs to calculate hash values for the following strings.
Pattern itself
All the substrings of the text of length m which is the size of pattern.
Here’s how the hash value is typically calculated in Rabin-Karp:
Step 1: Choose a suitable base and a modulus:
Select a prime number ‘p‘ as the modulus. This choice helps avoid overflow issues
and ensures a good distribution of hash values.
Choose a base ‘b‘ (usually a prime number as well), which is often the size of the
character set (e.g., 256 for ASCII characters).
Step 2: Initialize the hash value:
Set an initial hash value ‘hash‘ to 0.
Step 3: Calculate the initial hash value for the pattern:
Iterate over each character in the pattern from left to right.
For each character ‘c’ at position ‘i’, calculate its contribution to the hash value as
‘c * (bpattern_length – i – 1) % p’ and add it to ‘hash‘.
This gives you the hash value for the entire pattern.
Step 4:Slide the pattern over the text:
Start by calculating the hash value for the first substring of the text that is the same
length as the pattern.
Step 5: Update the hash value for each subsequent substring:
To slide the pattern one position to the right, you remove the contribution of the leftmost
character and add the contribution of the new character on the right.
The formula for updating the hash value when moving from position ‘i’ to ‘i+1’ is:
hash = (hash - (text[i - pattern_length] * (bpattern_length - 1)) % p) * b + text[i]
Step 6: Compare hash values:
When the hash value of a substring in the text matches the hash value of the
pattern, it’s a potential match.
If the hash values match, we should perform a character-by-character comparison
to confirm the match, as hash collisions can occur.
IMPLEMENTATION
OUTPUT
LAB PRACTICAL-12
Objective: Program for Hashing using Open Addressing
IMPLEMENTATION
OUTPUT