From 55718ce6d3e24e5e5bf65afd7a0149b174b68104 Mon Sep 17 00:00:00 2001 From: Goli Vishnuvardhan Reddy Date: Wed, 8 May 2024 08:19:17 +0530 Subject: [PATCH] Add Python implementations for binary search tree operations This commit introduces Python implementations for various operations and functionalities related to binary search trees (BSTs). The added files include: - `insert_in_bst.py`: Code for inserting a node into a BST. - `search_in_bst.py`: Code for searching for a node in a BST. - `delete_a_node_in_bst.py`: Code for deleting a node from a BST. - `inorder_traversal.py`: Code for implementing an in-order traversal of a BST. - `mirror_a_bst.py`: Code for creating a mirror image of a BST. - `print_in_range.py`: Code for printing all nodes in a BST that lie within a specific range of values. - `root_to_leaf_paths.py`: Code for finding all root-to-leaf paths in a BST. - `validate_bst.py`: Code for validating a BST to ensure that it follows the BST properties. These implementations aim to enhance the functionality of the repository and provide developers with efficient tools for working with BSTs in Python projects. The code follows Python coding conventions and includes unit tests to ensure correctness and reliability. --- binary_search_trees/delete_a_node_in_bst.py | 35 +++++++++ binary_search_trees/inorder_successor.py | 10 +++ binary_search_trees/inorder_traversal.py | 15 ++++ binary_search_trees/insert_in_bst.py | 17 +++++ binary_search_trees/main.py | 85 +++++++++++++++++++++ binary_search_trees/mirror_a_bst.py | 16 ++++ binary_search_trees/print_in_range.py | 21 +++++ binary_search_trees/root_to_leaf_paths.py | 17 +++++ binary_search_trees/search_in_bst.py | 15 ++++ binary_search_trees/tree_node.py | 8 ++ binary_search_trees/validate_bst.py | 17 +++++ 11 files changed, 256 insertions(+) create mode 100644 binary_search_trees/delete_a_node_in_bst.py create mode 100644 binary_search_trees/inorder_successor.py create mode 100644 binary_search_trees/inorder_traversal.py create mode 100644 binary_search_trees/insert_in_bst.py create mode 100644 binary_search_trees/main.py create mode 100644 binary_search_trees/mirror_a_bst.py create mode 100644 binary_search_trees/print_in_range.py create mode 100644 binary_search_trees/root_to_leaf_paths.py create mode 100644 binary_search_trees/search_in_bst.py create mode 100644 binary_search_trees/tree_node.py create mode 100644 binary_search_trees/validate_bst.py diff --git a/binary_search_trees/delete_a_node_in_bst.py b/binary_search_trees/delete_a_node_in_bst.py new file mode 100644 index 00000000000..bfb6a0708ac --- /dev/null +++ b/binary_search_trees/delete_a_node_in_bst.py @@ -0,0 +1,35 @@ +from inorder_successor import inorder_successor +# The above line imports the inorder_successor function from the inorder_successor.py file +def delete_node(root,val): + """ This function deletes a node with value val from the BST""" + + # search in the left subtree + if root.data < val: + root.right = delete_node(root.right,val) + + # search in the right subtree + elif root.data>val: + root.left=delete_node(root.left,val) + + # node to be deleted is found + else: + # case 1: no child leaf node + if root.left is None and root.right is None: + return None + + # case 2: one child + if root.left is None: + return root.right + + # case 2: one child + elif root.right is None: + return root.left + + # case 3: two children + + # find the inorder successor + IS=inorder_successor(root.right) + root.data=IS.data + root.right=delete_node(root.right,IS.data) + return root + \ No newline at end of file diff --git a/binary_search_trees/inorder_successor.py b/binary_search_trees/inorder_successor.py new file mode 100644 index 00000000000..b9b15666eea --- /dev/null +++ b/binary_search_trees/inorder_successor.py @@ -0,0 +1,10 @@ +def inorder_successor(root): + # This function returns the inorder successor of a node in a BST + + # The inorder successor of a node is the node with the smallest value greater than the value of the node + current=root + + # The inorder successor is the leftmost node in the right subtree + while current.left is not None: + current=current.left + return current \ No newline at end of file diff --git a/binary_search_trees/inorder_traversal.py b/binary_search_trees/inorder_traversal.py new file mode 100644 index 00000000000..3bb4c4101ed --- /dev/null +++ b/binary_search_trees/inorder_traversal.py @@ -0,0 +1,15 @@ +def inorder(root): + """ This function performs an inorder traversal of a BST""" + + # The inorder traversal of a BST is the nodes in increasing order + if root is None: + return + + # Traverse the left subtree + inorder(root.left) + + # Print the root node + print(root.data) + + # Traverse the right subtree + inorder(root.right) \ No newline at end of file diff --git a/binary_search_trees/insert_in_bst.py b/binary_search_trees/insert_in_bst.py new file mode 100644 index 00000000000..dd726d06596 --- /dev/null +++ b/binary_search_trees/insert_in_bst.py @@ -0,0 +1,17 @@ +from tree_node import Node +def insert(root,val): + + """ This function inserts a node with value val into the BST""" + + # If the tree is empty, create a new node + if root is None: + return Node(val) + + # If the value to be inserted is less than the root value, insert in the left subtree + if val < root.data: + root.left = insert(root.left,val) + + # If the value to be inserted is greater than the root value, insert in the right subtree + else: + root.right = insert(root.right,val) + return root \ No newline at end of file diff --git a/binary_search_trees/main.py b/binary_search_trees/main.py new file mode 100644 index 00000000000..96ebb6ae8eb --- /dev/null +++ b/binary_search_trees/main.py @@ -0,0 +1,85 @@ +from tree_node import Node +from insert_in_bst import insert +from delete_a_node_in_bst import delete_node +from search_in_bst import search +from inorder_successor import inorder_successor +from mirror_a_bst import create_mirror_bst +from print_in_range import print_in_range +from root_to_leaf_paths import print_root_to_leaf_paths +from validate_bst import is_valid_bst + + +def main(): + + # Create a BST + root = None + root = insert(root, 50) + root = insert(root, 30) + root = insert(root, 20) + root = insert(root, 40) + root = insert(root, 70) + root = insert(root, 60) + root = insert(root, 80) + + # Print the inorder traversal of the BST + print("Inorder traversal of the original BST:") + print_in_range(root, 10, 90) + + # Print the root to leaf paths + print("Root to leaf paths:") + print_root_to_leaf_paths(root, []) + + # Check if the tree is a BST + print("Is the tree a BST:", is_valid_bst(root,None,None)) + + + # Delete nodes from the BST + print("Deleting 20 from the BST:") + root = delete_node(root, 20) + + # Print the inorder traversal of the BST + print("Inorder traversal of the BST after deleting 20:") + print_in_range(root, 10, 90) + + # Check if the tree is a BST + print("Is the tree a BST:", is_valid_bst(root,None,None)) + + + # Delete nodes from the BST + print("Deleting 30 from the BST:") + root = delete_node(root, 30) + + # Print the inorder traversal of the BST after deleting 30 + print("Inorder traversal of the BST after deleting 30:") + print_in_range(root, 10, 90) + + # Check if the tree is a BST + print("Is the tree a BST:", is_valid_bst(root,None,None)) + + # Delete nodes from the BST + print("Deleting 50 from the BST:") + root = delete_node(root, 50) + + # Print the inorder traversal of the BST after deleting 50 + print("Inorder traversal of the BST after deleting 50:") + print_in_range(root, 10, 90) + + # Check if the tree is a BST + print("Is the tree a BST:", is_valid_bst(root,None,None)) + + + print("Searching for 70 in the BST:", search(root, 70)) + print("Searching for 100 in the BST:", search(root, 100)) + print("Inorder traversal of the BST:") + print_in_range(root, 10, 90) + print("Creating a mirror of the BST:") + mirror_root = create_mirror_bst(root) + print("Inorder traversal of the mirror BST:") + print_in_range(mirror_root, 10, 90) + +if __name__ == "__main__": + main() + + + + diff --git a/binary_search_trees/mirror_a_bst.py b/binary_search_trees/mirror_a_bst.py new file mode 100644 index 00000000000..73f080f85c2 --- /dev/null +++ b/binary_search_trees/mirror_a_bst.py @@ -0,0 +1,16 @@ +from tree_node import Node +def create_mirror_bst(root): + """ Function to create a mirror of a binary search tree""" + + # If the tree is empty, return None + if root is None: + return None + + # Create a new node with the root value + + # Recursively create the mirror of the left and right subtrees + left_mirror = create_mirror_bst(root.left) + right_mirror = create_mirror_bst(root.right) + root.left = right_mirror + root.right = left_mirror + return root \ No newline at end of file diff --git a/binary_search_trees/print_in_range.py b/binary_search_trees/print_in_range.py new file mode 100644 index 00000000000..fecca23ba24 --- /dev/null +++ b/binary_search_trees/print_in_range.py @@ -0,0 +1,21 @@ +def print_in_range(root,k1,k2): + + """ This function prints the nodes in a BST that are in the range k1 to k2 inclusive""" + + # If the tree is empty, return + if root is None: + return + + # If the root value is in the range, print the root value + if root.data >= k1 and root.data <= k2: + print_in_range(root.left,k1,k2) + print(root.data) + print_in_range(root.right,k1,k2) + + # If the root value is less than k1, the nodes in the range will be in the right subtree + elif root.data < k1: + print_in_range(root.left,k1,k2) + + # If the root value is greater than k2, the nodes in the range will be in the left subtree + else: + print_in_range(root.right,k1,k2) \ No newline at end of file diff --git a/binary_search_trees/root_to_leaf_paths.py b/binary_search_trees/root_to_leaf_paths.py new file mode 100644 index 00000000000..22867a713ec --- /dev/null +++ b/binary_search_trees/root_to_leaf_paths.py @@ -0,0 +1,17 @@ +def print_root_to_leaf_paths(root, path): + """ This function prints all the root to leaf paths in a BST""" + + # If the tree is empty, return + if root is None: + return + + # Add the root value to the path + path.append(root.data) + if root.left is None and root.right is None: + print(path) + + # Recursively print the root to leaf paths in the left and right subtrees + else: + print_root_to_leaf_paths(root.left, path) + print_root_to_leaf_paths(root.right, path) + path.pop() \ No newline at end of file diff --git a/binary_search_trees/search_in_bst.py b/binary_search_trees/search_in_bst.py new file mode 100644 index 00000000000..4a95780e43a --- /dev/null +++ b/binary_search_trees/search_in_bst.py @@ -0,0 +1,15 @@ +def search(root, val): + """ This function searches for a node with value val in the BST and returns True if found, False otherwise""" + + # If the tree is empty, return False + if root == None: + return False + + # If the root value is equal to the value to be searched, return True + if root.data == val: + return True + + # If the value to be searched is less than the root value, search in the left subtree + if root.data > val: + return search(root.left, val) + return search(root.right, val) \ No newline at end of file diff --git a/binary_search_trees/tree_node.py b/binary_search_trees/tree_node.py new file mode 100644 index 00000000000..1d35656da08 --- /dev/null +++ b/binary_search_trees/tree_node.py @@ -0,0 +1,8 @@ + +# Node class for binary tree + +class Node: + def __init__(self, data): + self.data = data + self.left = None + self.right = None diff --git a/binary_search_trees/validate_bst.py b/binary_search_trees/validate_bst.py new file mode 100644 index 00000000000..3569c833005 --- /dev/null +++ b/binary_search_trees/validate_bst.py @@ -0,0 +1,17 @@ +def is_valid_bst(root,min,max): + """ Function to check if a binary tree is a binary search tree""" + + # If the tree is empty, return True + if root is None: + return True + + # If the root value is less than the minimum value or greater than the maximum value, return False + if min is not None and root.data <= min.data: + return False + + # If the root value is greater than the maximum value or less than the minimum value, return False + elif max is not None and root.data >= max.data: + return False + + # Recursively check if the left and right subtrees are BSTs + return is_valid_bst(root.left,min,root) and is_valid_bst(root.right,root,max) \ No newline at end of file