A Binary tree T is a Binary Search Tree (BST), if each node N of T has the following property : The value at N is greater than every value in the left subtree of N and is less than every value in the right subtree of N.
A Binary Search Tree (BST) is a special type of binary tree in which the left child of a node has a value less than the node’s value and the right child has a value greater than the node’s value. This property is called the BST property and it makes it possible to efficiently search, insert, and delete elements in the tree.
BST are used to maintain a dynamically changing dataset in sorted order, which allows for quick lookup, addition, and removal of items.
BSTs support several fundamental operations, which are efficient due to their ordered nature. Here’s an overview of the primary operations:
Insertion in a BST involves adding a new node while maintaining the BST property: for any given node, all elements in its left subtree are less than the node, and all elements in its right subtree are greater.
Function Insert(root, value):
If root is NULL:
root = CreateNode(value)
return root
If value < root.value:
If root.left is NULL:
root.left = CreateNode(value)
Else:
Insert(root.left, value)
Else If value > root.value:
If root.right is NULL:
root.right = CreateNode(value)
Else:
Insert(root.right, value)
return root
Searching in a BST is efficient due to its sorted nature. You can determine the direction to move at each step (left or right).
Function Search(root, value):
If root is NULL or root.value is value:
return root
If value < root.value:
return Search(root.left, value)
Else:
return Search(root.right, value)
Deletion in a BST can be a bit tricky, as it needs to ensure that the BST property is maintained after removing a node. There are three cases to consider
Function Delete(root, value):
If root is NULL:
return root
If value < root.value:
root.left = Delete(root.left, value)
Else If value > root.value:
root.right = Delete(root.right, value)
Else:
// Node with only one child or no child
If root.left is NULL:
temp = root.right
Free(root)
return temp
Else If root.right is NULL:
temp = root.left
Free(root)
return temp
// Node with two children: Get the inorder successor
temp = MinValueNode(root.right)
// Copy the inorder successor's content to this node
root.value = temp.value
// Delete the inorder successor
root.right = Delete(root.right, temp.value)
return root
Function MinValueNode(node):
current = node
// Loop down to find the leftmost leaf
While current.left is not NULL:
current = current.left
return current
Traversal operations go through the nodes of the tree in a specific order. Common traversal methods include in-order, pre-order, and post-order.
Each traversal serves different purposes and can be chosen based on the specific needs of the algorithm or application.
Function InOrderTraversal(root):
If root is not NULL:
InOrderTraversal(root.left)
Print root.value
InOrderTraversal(root.right)
// Binary Search Tree operations in C
#include <stdio.h>
#include <stdlib.h>
struct node
{
int key;
struct node *left, *right;
};
// Create a node
struct node *newNode(int item)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
// Inorder Traversal
void inorder(struct node *root)
{
if (root != NULL)
{ // Traverse left
inorder(root->left);
// Traverse root
printf("%d -> ", root->key);
// Traverse right
inorder(root->right);
}
}
// preorder Traversal
void preorder(struct node *root)
{
if (root != NULL)
{
printf("%d -> ", root->key);
preorder(root->left);
preorder(root->right);
}
}
// postorder Traversal
void postorder(struct node *root)
{
if (root != NULL)
{
postorder(root->left);
postorder(root->right);
printf("%d -> ", root->key);
}
}
// Insert a node
struct node *insert(struct node *node, int key)
{ // Return a new node if the tree is empty
if (node == NULL)
return newNode(key);
// Traverse to the right place and insert the node
if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
return node;
}
// Find the inorder successor
struct node *minValueNode(struct node *node)
{
struct node *current = node;
// Find the leftmost leaf
while (current && current->left != NULL)
current = current->left;
return current;
}
// Deleting a node
struct node *deleteNode(struct node *root, int key)
{ // Return if the tree is empty
if (root == NULL)
return root;
// Find the node to be deleted
if (key < root->key)
root->left = deleteNode(root->left, key);
else if (key > root->key)
root->right = deleteNode(root->right, key);
else
{
// If the node is with only one child or no child
if (root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}
// If the node has two children
struct node *temp = minValueNode(root->right);
// Place the inorder successor in position of the node to be deleted
root->key = temp->key;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
return root;
}
// Function to free memory by deallocating nodes
void freeMemory(struct node *root)
{
if (root == NULL)
return;
freeMemory(root->left);
freeMemory(root->right);
free(root);
}
int main() {
int choice,value;
struct node *root = NULL;
do
{
printf("\n1. Insertion\n2. Deletion\n3. inorder\n4. preorder\n5. postorder\n6. Exit");
printf("\nEnter your choice: ");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Enter the value to be insert: ");
scanf("%d",&value);
root = insert(root, value);
break;
case 2: printf("Enter the value to be deleted: ");
scanf("%d",&value);
root = deleteNode(root, value);
break;
case 3: inorder(root);
break;
case 4: preorder(root);
break;
case 5: postorder(root);
break;
case 6: freeMemory(root);
break;
default: printf("\nWrong selection!!! Try again!!!");
}
}while(choice!=6);
return (0);
}