0% found this document useful (0 votes)
4 views

ADS LAB

The document outlines various lab practicals focused on data structures, specifically Binary Search Trees (BST), AVL Trees, and Skip Lists. It details algorithms for insertion, searching, and deletion operations, along with traversal methods for BSTs and the concept of balancing in AVL Trees. Additionally, it covers string matching algorithms, including the Naïve and Rabin-Karp methods, providing implementation examples and expected outputs.

Uploaded by

productionsankit
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

ADS LAB

The document outlines various lab practicals focused on data structures, specifically Binary Search Trees (BST), AVL Trees, and Skip Lists. It details algorithms for insertion, searching, and deletion operations, along with traversal methods for BSTs and the concept of balancing in AVL Trees. Additionally, it covers string matching algorithms, including the Naïve and Rabin-Karp methods, providing implementation examples and expected outputs.

Uploaded by

productionsankit
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 16

LAB PRACTICAL-1

Objective: Program for Insertion in Binary Search Tree.


Binary Search Tree is a node-based binary tree data structure which has the following
properties:
 The left subtree of a node contains only nodes with keys lesser than the node’s
key.
 The right subtree of a node contains only nodes with keys greater than the node’s
key.
 The left and right subtree each must also be a binary search tree.

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 1: IF TREE = NULL


Allocate memory for TREE
SET TREE -> DATA = ITEM
SET TREE -> LEFT = TREE -> RIGHT = NULL
ELSE
IF ITEM < TREE -> DATA
Insert(TREE -> LEFT, ITEM)
ELSE
Insert(TREE -> RIGHT, ITEM)
[END OF IF]
[END OF IF]

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 1: IF TREE = NULL


Write "item not found in the tree" ELSE IF ITEM < TREE -> DATA
Delete(TREE->LEFT, ITEM)
ELSE IF ITEM > TREE -> DATA
Delete(TREE -> RIGHT, ITEM)
ELSE IF TREE -> LEFT AND TREE -> RIGHT
SET TEMP = findLargestNode(TREE -> LEFT)
SET TREE -> DATA = TEMP -> DATA
Delete(TREE -> LEFT, TEMP -> DATA)
ELSE
SET TEMP = TREE
IF TREE -> LEFT = NULL AND TREE -> RIGHT = NULL
SET TREE = NULL
ELSE IF TREE -> LEFT != NULL
SET TREE = TREE -> LEFT
ELSE
SET TREE = TREE -> RIGHT
[END OF IF]
FREE TEMP
[END OF IF]

Step 2: END
IMPLEMENTATION
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None

# Note that it is not a generic inorder successor


# function. It mainly works when the right child
# is not empty, which is the case we need in BST
# delete.
def get_successor(curr):
curr = curr.right
while curr is not None and curr.left is not None:
curr = curr.left
return curr

# This function deletes a given key x from the


# given BST and returns the modified root of the
# BST (if it is modified).
def del_node(root, x):

# Base case
if root is None:
return root

# If key to be searched is in a subtree


if root.key > x:
root.left = del_node(root.left, x)
elif root.key < x:
root.right = del_node(root.right, x)

else:
# If root matches with the given key

# Cases when root has 0 children or


# only right child
if root.left is None:
return root.right

# When root has only left child


if root.right is None:
return root.left

# When both children are present


succ = get_successor(root)
root.key = succ.key
root.right = del_node(root.right, succ.key)
return root

# Utility function to do inorder traversal


def inorder(root):
if root is not None:
inorder(root.left)
print(root.key, end=" ")
inorder(root.right)

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

INSERTION IN AVL TREE

 Insert as in a Binary Search Tree (BST):


Insert the new node in the correct position based on BST properties.

 Update Heights:
After the insertion, update the height of the ancestor nodes.

 Calculate Balance Factor:


For each node, compute the balance factor. A balance factor of −1, 0 or 1 is considered
balanced.

 Check for Imbalance:


If the balance factor is outside the range [−1,1], the tree is unbalanced, and rotations are
needed to restore balance.

Types of Rotations (Cases)


Case 1: Left-Left (LL) Rotation

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.

Steps for Right Rotation:

1. The left child becomes the new root.


2. The original root becomes the right child of the new root.
3. The right subtree of the new root becomes the left subtree of the original root.

Case 2: Right-Right (RR) Rotation

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.

Steps for Left Rotation:

1. The right child becomes the new root.


2. The original root becomes the left child of the new root.
3. The left subtree of the new root becomes the right subtree of the original root.

Case 3: Left-Right (LR) Rotation

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.

Case 4: Right-Left (RL) Rotation

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.

Working of Skip List


This example has 14 nodes, such that these nodes are divided into two layers, as shown in the
diagram. The lower layer is a common line that links all nodes, and the top layer is an express
line that links only the main nodes, as you can see in the diagram. Suppose we want to find
47 in this example. We will start the search from the first node of the express line and
continue running on the express line until we find a node that is equal a 47 or more than 47.
We see in the example that 47 does not exist in the express line, so we search for a node of
less than 47, which is 40. Now, we go to the normal line with the help of 40, and search the
47.

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

def search_pattern(pattern, text):


m = len(pattern)
n = len(text)
for i in range(n - m + 1):
j=0
while j < m and text[i + j] == pattern[j]:
j += 1
if j == m:
print(f"Pattern found at index {i}")
if __name__ == "__main__":
text = input("Enter the text: ")
pattern = input("Enter the pattern: ")
print("\nSearching for the pattern in the text...")
search_pattern(pattern, text)

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

def rabin_karp_search(text, pattern, q):


M = len(pattern)
N = len(text)
d = 256
p=0
t=0
h=1
# h = (d^(M-1)) % q
for i in range(M-1):
h = (h * d) % q
for i in range(M):
p = (d * p + ord(pattern[i])) % q
t = (d * t + ord(text[i])) % q
# Slide the pattern over the text one by one
for i in range(N - M + 1):
if p == t:
for j in range(M):
if text[i + j] != pattern[j]:
break
if j == M - 1:
print(f"Pattern found at index {i}")
if i < N - M:
t = (d * (t - ord(text[i]) * h) + ord(text[i + M])) % q
if t < 0:
t=t+q
if __name__ == "__main__":
text = "AAAAKANKSHAJOSHIJKJK"
pattern = "JOSHIJKJK"
q = 101
rabin_karp_search(text, pattern, q)

OUTPUT
LAB PRACTICAL-12
Objective: Program for Hashing using Open Addressing

IMPLEMENTATION
OUTPUT

You might also like