Binary Search Tree
Binary Search Tree
Finally, we can find the node with value 10 in minimal search count. That's
how the binary search tree effectively improves the data manipulation.
In normal array and linked list, there is no way we can skip some element from
the searching as they don't follow any data arrangement rules like the binary
search tree.
//declaring a node
struct node *root;
Example:
Algorithm:
1. Create a new BST node and assign values to it.
2. insert(node, key)
i) If root == NULL,
return the new node to the calling function.
ii) if root=>data < key
call the insert function with root=>right and assign the return value
in root=>right.
root->right = insert(root=>right,key)
iii) if root=>data > key
call the insert function with root->left and assign the return value in
root=>left.
root=>left = insert(root=>left,key)
3. Finally, return the original root pointer to the calling function.
Binary search tree insertion code:
struct node *insert(struct node *root, int val)
{
/*
* It will handle two cases,
* 1. if the tree is empty, return new node in the root
* 2. if the tree traversal reaches NULL, it will return the new node
*/
if(root == NULL)
return getNewNode(val);
/*
* if given val is greater than root->key,
* we should find the correct place in the right subtree and insert the new node
*/
if(root->key < val)
root->right = insert(root->right,val);
/*
* if given val is smallar than root->key,
* we should find the correct place in the left subtree and insert the new node
*/
else if(root->key > val)
root->left = insert(root->left,val);
/*
* It will handle two cases
* (Prevent the duplicate nodes in the tree)
* 1.if root->key == val it will straight away return the address of the root node
* 2.After the insertion, it will return the original unchanged root's address
*/
return root;
}
The getNewNode function:
This function allocates and returns the new node with the given data and the left
and right pointer as NULL.
inorder(root);
return 0;
}
Output:
50 100 150
Preorder Traversal of Binary Search Tree:
Preorder traversal is one of the depth first tree traversal methods.
Preorder : Root - Left - Right
Algorithm:
Visit or print the root.
Traverse the left subtree.
Traverse the right subtree.
struct node
{
int key;
struct node *left;
struct node *right;
};
//return a new node with the given value
struct node *getNode(int val)
{
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->key = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
return root;
}
int main()
{
struct node *root = NULL;
root = insertNode(root,100);
root = insertNode(root, 50);
root = insertNode(root, 200);
root = insertNode(root, 10);
root = insertNode(root, 60);
root = insertNode(root, 150);
root = insertNode(root, 300);
preorder(root);
return 0;
}
Output:
100 50 10 60 200 150 300
Inorder Traversal of Binary Search Tree:
Inorder traversal is one of the depth first tree traversal methods.
Inorder traversal of binary search tree will produce the output in acending order.
Algorithm:
Traverse the left subtree.
Visit or print the root.
Traverse the right subtree.
Inorder traversal function:
void inorder(struct node *root)
{
if(root == NULL)
return;
struct node
{
int key;
struct node *left;
struct node *right;
};
//return a new node with the given value
struct node *getNode(int val)
{
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->key = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
return root;
}
int main()
{
struct node *root = NULL;
root = insertNode(root,100);
root = insertNode(root, 50);
root = insertNode(root, 200);
root = insertNode(root, 10);
root = insertNode(root, 60);
root = insertNode(root, 150);
root = insertNode(root, 300);
inorder(root);
return 0;
}
Output:
10 50 60 100 150 200 300
Postorder Traversal of Binary Search Tree:
Postorder traversal is one of the depth first tree traversal methods.
Postorder : Left - Right - Root
Algorithm:
Traverse the left subtree.
Traverse the right subtree.
Visit or print the root.
#include<stdio.h>
#include<stdlib.h>
struct node
{
int key;
struct node *left;
struct node *right;
};
//return a new node with the given value
struct node *getNode(int val)
{
struct node *newNode;
newNode = malloc(sizeof(struct node));
newNode->key = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
return root;
}
int main()
{
struct node *root = NULL;
root = insertNode(root,100);
root = insertNode(root, 50);
root = insertNode(root, 200);
root = insertNode(root, 10);
root = insertNode(root, 60);
root = insertNode(root, 150);
root = insertNode(root, 300);
postorder(root);
return 0;
}
Output:
10 60 50 150 300 200 100
Deletion in Binary Search Tree:
To delete the given node from the binary search tree(BST), we should follow the
below rules.
1.Leaf Node
If the node is leaf (both left and right will be NULL), remove the node directly
and free its memory.
2.Node with Right Child:
If the node has only right child (left will be NULL), make the node points to the
right node and free the node.
Example
3.Node with Left Child:
If the node has only left child (right will be NULL), make the node points to
the left node and free the node.
Example:
4.Node has both left and right child:
If the node has both left and right child,
1.find the smallest node in the right subtree. say min
2.make node->data = min
3.Again delete the min node.
Example:
Remove function with algorithm explanation:
struct node *removeNode(struct node *root, int val)
{
/*
* If the node becomes NULL, it will return NULL
* Two possible ways which can trigger this case
* 1. If we send the empty tree. i.e root == NULL
* 2. If the given node is not present in the tree.
*/
if(root == NULL)
return NULL;
/*
* If root->key < val. val must be present in the right subtree
* So, call the above remove function with root->right
*/
if(root->key < val)
root->right = removeNode(root->right,val);
/*
* if root->key > val. val must be present in the left subtree
* So, call the above function with root->left
*/
else if(root->key > val)
root->left = removeNode(root->left,val);
/*
* This part will be executed only if the root->key == val
* The actual removal starts from here
*/
else
{
/*
* Case 1: Leaf node. Both left and right reference is NULL
* replace the node with NULL by returning NULL to the calling pointer.
* free the node
*/
if(root->left == NULL && root->right == NULL)
{
free(root);
return NULL;
}
/*
* Case 2: Node has right child.
* replace the root node with root->right and free the right node
*/
else if(root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
/*
* Case 3: Node has left child.
* replace the node with root->left and free the left node
*/
else if(root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}
/*
* Case 4: Node has both left and right children.
* Find the min value in the right subtree
* replace node value with min.
* And again call the remove function to delete the node which has the min
value.
* Since we find the min value from the right subtree call the remove function
with root->right.
*/
else
{
int rightMin = getRightMin(root->right);
root->key = rightMin;
root->right = removeNode(root->right,rightMin);
}
#include<stdio.h>
#include<stdlib.h>
struct node
{
int key;
struct node *left;
struct node *right;
};
struct node *getNewNode(int val)
{
struct node *newNode = malloc(sizeof(struct node));
newNode->key = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
return root;
}
return temp->key;
}
struct node *removeNode(struct node *root, int val)
{
/*
* If the node becomes NULL, it will return NULL
* Two possible ways which can trigger this case
* 1. If we send the empty tree. i.e root == NULL
* 2. If the given node is not present in the tree.
*/
if(root == NULL)
return NULL;
/*
* If root->key < val. val must be present in the right subtree
* So, call the above remove function with root->right
*/
if(root->key < val)
root->right = removeNode(root->right,val);
/*
* if root->key > val. val must be present in the left subtree
* So, call the above function with root->left
*/
else if(root->key > val)
root->left = removeNode(root->left,val);
/*
* This part will be executed only if the root->key == val
* The actual removal starts from here
*/
else
{
/*
* Case 1: Leaf node. Both left and right reference is NULL
* replace the node with NULL by returning NULL to the calling pointer.
* free the node
*/
if(root->left == NULL && root->right == NULL)
{
free(root);
return NULL;
}
/*
* Case 2: Node has right child.
* replace the root node with root->right and free the right node
*/
else if(root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
/*
* Case 3: Node has left child.
* replace the node with root->left and free the left node
*/
else if(root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}
/*
* Case 4: Node has both left and right children.
* Find the min value in the right subtree
* replace node value with min.
* And again call the remove function to delete the node which has the min
value.
* Since we find the min value from the right subtree call the remove function
with root->right.
*/
else
{
int rightMin = getRightMin(root->right);
root->key = rightMin;
root->right = removeNode(root->right,rightMin);
}
int main()
{
/*
100
/\
50 200
/ \
150 300
*/
struct node *root = NULL;
root = insert(root,100);
root = insert(root,50);
root = insert(root,200);
root = insert(root,150);
root = insert(root,300);
return 0;
}
Output:
Initial tree : 50 100 150 200 300
After deletion of 300, the new tree : 50 100 150 200
After deletion of 100, the new tree : 50 150 200
END