Binary Search Tree (BST)
Overviewβ
A Binary Search Tree (BST) is a binary tree where each node follows the binary search property:
- The left subtree of a node contains only nodes with values less than the node's key.
- The right subtree of a node contains only nodes with values greater than the node's key.
- Both left and right subtrees must also be binary search trees.
BSTs are commonly used for searching, insertion, and deletion operations, all of which can be performed efficiently with an average time complexity of O(log n) for balanced trees.
Featuresβ
- Efficient Search: Lookup operations are performed in O(log n) time.
- Insertion: New elements are added in the correct position in O(log n) time.
- Deletion: Nodes can be removed while maintaining the binary search property.
- Traversal: In-order, pre-order, and post-order traversals are supported to explore tree elements.
- Balanced Tree Variants: Variants like AVL and Red-Black trees ensure balancing to maintain performance.
Table of Contentsβ
How It Worksβ
In a BST:
- Each node contains a value (key), a pointer to the left child, and a pointer to the right child.
- The left subtree contains values smaller than the nodeβs key.
- The right subtree contains values greater than the nodeβs key.
Binary Search Property:β
- For every node
N
, all values in the left subtree are smaller thanN
. - All values in the right subtree are greater than
N
.
Operationsβ
Insertionβ
To insert a new value:
- Start at the root.
- Recursively move to the left or right subtree depending on whether the new value is smaller or greater than the current node.
- Insert the new value in the appropriate position once you find an empty subtree.
Deletionβ
Deletion is performed in three cases:
- Node has no children: Simply remove the node.
- Node has one child: Replace the node with its child.
- Node has two children: Replace the node with its in-order predecessor or successor (the largest value in the left subtree or the smallest value in the right subtree).
Searchβ
To search for a value:
- Start at the root.
- Recursively traverse left if the value is smaller, or right if it's larger.
- Stop when you find the value or hit a
null
pointer.
Traversalβ
- In-Order Traversal: Left subtree β Root β Right subtree.
- Pre-Order Traversal: Root β Left subtree β Right subtree.
- Post-Order Traversal: Left subtree β Right subtree β Root.
Code Exampleβ
Python Example:β
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.value = key
class BinarySearchTree:
def __init__(self):
self.root = None
def insert(self, key):
if self.root is None:
self.root = Node(key)
else:
self._insert(self.root, key)
def _insert(self, node, key):
if key < node.value:
if node.left is None:
node.left = Node(key)
else:
self._insert(node.left, key)
else:
if node.right is None:
node.right = Node(key)
else:
self._insert(node.right, key)
def inorder(self):
self._inorder(self.root)
def _inorder(self, node):
if node:
self._inorder(node.left)
print(node.value, end=" ")
self._inorder(node.right)
# Example usage:
bst = BinarySearchTree()
bst.insert(50)
bst.insert(30)
bst.insert(70)
bst.insert(20)
bst.insert(40)
bst.insert(60)
bst.insert(80)
print("Inorder traversal:")
bst.inorder()
Output:β
Inorder traversal:
20 30 40 50 60 70 80
Applicationsβ
- Search Applications: Used to store data for fast lookup, like phone directories or databases.
- In-Memory Data: Efficient for in-memory data representation where fast insertion, deletion, and lookup are required.
- Sorting: In-order traversal gives a sorted sequence of elements in the BST.
Time Complexityβ
Operation | Average Time | Worst Case Time (Unbalanced) |
---|---|---|
Search | O(log n) | O(n) |
Insertion | O(log n) | O(n) |
Deletion | O(log n) | O(n) |
Traversal | O(n) | O(n) |
Note: In a balanced BST (like AVL or Red-Black Tree), all operations maintain an O(log n) time complexity. In an unbalanced BST, the time complexity can degrade to O(n) in the worst case (degenerating into a linked list).
Conclusionβ
A Binary Search Tree is an essential data structure for efficient data management, offering quick search, insertion, and deletion operations. Understanding its structure and algorithms is crucial for optimizing tasks that involve dynamic sets of data.