A Binary search tree is a binary tree where the values of the left sub-tree are less than the root node and the values of the right sub-tree are greater than the value of the root node. In this article, we will discuss the binary search tree in Python.
What is a Binary Search Tree(BST)?
A Binary Search Tree is a data structure used in computer science for organizing and storing data in a sorted manner. Each node in a Binary Search Tree has at most two children, a left child and a right child.
Properties of BST
The left side of a node only has smaller values.
The right side of a node only has bigger values.
Both the left and right sides follow the same rule, forming a smaller binary search tree.
Binary Search Tree
In this binary tree
Root node: 8
Left subtree (3): values < 8
Right subtree (10): values > 8
Each subtree maintains the same rule, with values relative to their respective roots.
Creation of Binary Search Tree (BST) in Python
Below, are the steps to create a Binary Search Tree (BST).
Create a class Tree
In the parameterized constructor, we have the default parameter val = None
When the Tree class is instantiated without any parameter then it creates an empty node with left and right pointers
If we pass the value while instantiating then it creates a node having that value and left, right pointers are created with None Types.
Python
classNode:def__init__(self,key):self.value=keyself.left=Noneself.right=None# Creating the root noderoot=Node(5)
Time complexity: O(1) Space complexity: O(1)
Basic Operations on Binary Search Tree (BST)
Below, are the some basic Operations of Binary Search Tree(BST) in Python.
Inserting a node in a Binary search tree involves adding a new node to the tree while maintaining the binary search tree (BST) property. So we need to traverse through all the nodes till we find a leaf node and insert the node as the left or right child based on the value of that leaf node. So the three conditions that we need to check at the leaf node are listed below:
Illustrations
Let us insert 13 into the below Binary search tree
Binary Search Tree
When we call the insert method then 13 is checked with the root node which is 15 , Since 13 < 15 we need to insert 13 to the left sub tree. So we recursively call left_sub_tree.insert(13)
Now the left child of 15 is 10 so 13 is checked with 10 and since 13>10 we need to insert 13 to the right sub tree. So we recursively call right_sub_tree.insert(13)
Here, the right child of 10 is 11 so 13 is checked with 11 and since 13>11 and we need to insert 13 to the right child of 11. Again we recursively call right_sub_tree.insert(13)
In this recursion call, we found there is no node which means we reached till the leaf node, so we create a node and insert the data in the node
After inserting 13 , the BST looks like this :
Inserted 13 Node in Binary Search Tree
Insertion in Binary Search Tree (BST) in Python
Python
# Python program to demonstrate# insert operation in binary search treeclassNode:def__init__(self,key):self.left=Noneself.right=Noneself.val=key# A utility function to insert# a new node with the given keydefinsert(root,key):ifrootisNone:returnNode(key)ifroot.val==key:returnrootifroot.val<key:root.right=insert(root.right,key)else:root.left=insert(root.left,key)returnroot# A utility function to do inorder tree traversaldefinorder(root):ifroot:inorder(root.left)print(root.val,end=" ")inorder(root.right)r=Node(15)r=insert(r,10)r=insert(r,18)r=insert(r,4)r=insert(r,11)r=insert(r,16)r=insert(r,20)r=insert(r,13)# Print inorder traversal of the BSTinorder(r)
Output
4 10 11 13 15 16 18 20
Time Complexity:
The worst-case time complexity of insert operations is O(h) where h is the height of the Binary Search Tree.
In the worst case, we may have to travel from the root to the deepest leaf node. The height of a skewed tree may become n and the time complexity of insertion operation may become O(n).
Auxiliary Space: The auxiliaryspace complexity of insertion into a binary search tree is O(1)
Searching in Binary Search Tree in Python
Searching in Binary Search Tree is very easy because we don't need to traverse all the nodes. It is based on the value of nodes,which means if the value is less than root then we search in the left sub tree or else we search in right sub tree.
Illustrations
Steps to search a value 'v' in BST:
The value is checked with the root node, if it is equal to the root node then it returns the value
If the value is less than root node then it recursively calls the search operation in the left sub tree
If the value is greater than root node then it recursively calls the search operation in the right sub tree
Binary Search Tree
In above example BST search for value '8' begins from the root node.
If the value is not equal to the current node's value, the search continues recursively on the left subtree if the value is less than the current node's value.
Once the value matches a node, the search terminates, returning the node containing the value.
Searching in Binary Search Tree (BST) in Python
Python
classNode:def__init__(self,key):self.key=keyself.left=Noneself.right=None# function to search a key in a BSTdefsearch(root,key):# Base Cases: root is null or key # is present at rootifrootisNoneorroot.key==key:returnroot# Key is greater than root's keyifroot.key<key:returnsearch(root.right,key)# Key is smaller than root's keyreturnsearch(root.left,key)# Creating a hard coded tree for keeping # the length of the code small. We need # to make sure that BST properties are # maintained if we try some other cases.root=Node(50)root.left=Node(30)root.right=Node(70)root.left.left=Node(20)root.left.right=Node(40)root.right.left=Node(60)root.right.right=Node(80)# Searching for keys in the BSTprint("Found"ifsearch(root,19)else"Not Found")print("Found"ifsearch(root,80)else"Not Found")
Output
Not Found
Found
Time complexity: O(h), where h is the height of the BST. Auxiliary Space: O(h) This is because of the space needed to store the recursion stack.
Deletion in Binary Search Tree in Python
Deleting a node in Binary search tree involves deleting an existing node while maintaining the properties of Binary Search Tree(BST). we need to search the node which needs to be deleted and then delete it.
Case 1 : While deleting a node having both left child and right child
After finding the node to be deleted, copy the value of right child to v and copy the right child's left pointer to left of v and right pointer
Delete node 18 in BST
In the above example, suppose we need to delete 18 then we need to replace 18 with the maximum value of its left or right sub tree
Let us replace it with 20 which is maximum value of right sub tree
So after deleting 18, the Binary search tree looks like this
Case 2 : While deleting a node having either left child or right child
After finding the node to be deleted, we need to replace the value in the node with its left node it has left child or right node if it has right child.
Delete 16 in BST
In the above example, suppose we need to delete 16 then we need to replace 16 with the value of its right child node
So it will be replaced with 17 which is the value of its right child node
So after deleting 16, the Binary search tree looks like this
Deleted 16 in BST
Case 3 : While deleting a leaf node(a node which has no child)
Delete 4 in BST
In the above example, suppose we need to delete 4 which is a leaf node.
Simply we change value of the node, left and right pointers to None.
After deleting 4 the BST looks like this:
Deleted 4 in BST
Deletion in Binary Search Tree in Python
Python
classNode:def__init__(self,key):self.key=keyself.left=Noneself.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.defget_successor(curr):curr=curr.rightwhilecurrisnotNoneandcurr.leftisnotNone:curr=curr.leftreturncurr# This function deletes a given key x from the# given BST and returns the modified root of the # BST (if it is modified).defdel_node(root,x):# Base caseifrootisNone:returnroot# If key to be searched is in a subtreeifroot.key>x:root.left=del_node(root.left,x)elifroot.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 childifroot.leftisNone:returnroot.right# When root has only left childifroot.rightisNone:returnroot.left# When both children are presentsucc=get_successor(root)root.key=succ.keyroot.right=del_node(root.right,succ.key)returnroot# Utility function to do inorder traversaldefinorder(root):ifrootisnotNone:inorder(root.left)print(root.key,end=" ")inorder(root.right)# Driver codeif__name__=="__main__":root=Node(10)root.left=Node(5)root.right=Node(15)root.right.left=Node(12)root.right.right=Node(18)x=15root=del_node(root,x)inorder(root)print()
Output
5 10 12 18
Time Complexity: O(h), where h is the height of the BST. Auxiliary Space: O(h).
Traversals in Binary Search Tree in Python
Below, are the traversals of Binary Search Tree (BST) in Python which we can perform as SImilar to Binary Tree.
# Python3 code to implement the approach# Class describing a node of treeclassNode:def__init__(self,v):self.left=Noneself.right=Noneself.data=v# Inorder TraversaldefprintInorder(root):ifroot:# Traverse left subtreeprintInorder(root.left)# Visit nodeprint(root.data,end=" ")# Traverse right subtreeprintInorder(root.right)# Driver codeif__name__=="__main__":# Build the treeroot=Node(100)root.left=Node(20)root.right=Node(200)root.left.left=Node(10)root.left.right=Node(30)root.right.left=Node(150)root.right.right=Node(300)# Function callprint("Inorder Traversal:",end=" ")printInorder(root)# This code is contributed by ajaymakvana.
Output
Inorder Traversal: 10 20 30 100 150 200 300
Time complexity: O(N), Where N is the number of nodes. Auxiliary Space: O(h), Where h is the height of tree
Applications of BST:
Graph algorithms: BSTs can be used to implement graph algorithms, such as in minimum spanning tree algorithms.
Priority Queues: BSTs can be used to implement priority queues, where the element with the highest priority is at the root of the tree, and elements with lower priority are stored in the subtrees.
Self-balancing binary search tree: BSTs can be used as a self-balancing data structures such as AVL tree and Red-black tree.
Data storage and retrieval: BSTs can be used to store and retrieve data quickly, such as in databases, where searching for a specific record can be done in logarithmic time.
Advantages:
Fast search: Searching for a specific value in a BST has an average time complexity of O(log n), where n is the number of nodes in the tree. This is much faster than searching for an element in an array or linked list, which have a time complexity of O(n) in the worst case.
In-order traversal: BSTs can be traversed in-order, which visits the left subtree, the root, and the right subtree. This can be used to sort a dataset.
Space efficient: BSTs are space efficient as they do not store any redundant information, unlike arrays and linked lists.
Disadvantages:
Skewed trees: If a tree becomes skewed, the time complexity of search, insertion, and deletion operations will be O(n) instead of O(log n), which can make the tree inefficient.
Additional time required: Self-balancing trees require additional time to maintain balance during insertion and deletion operations.
Efficiency: BSTs are not efficient for datasets with many duplicates as they will waste space.
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.