TheAlgorithms-C/data_structures/binary_trees/binary_search_tree.c

207 lines
5.6 KiB
C
Raw Normal View History

2017-10-14 09:31:40 +03:00
#include <stdio.h>
#include <stdlib.h>
2017-12-27 17:01:50 +03:00
/* A basic unbalanced binary search tree implementation in C, with the following functionalities implemented:
- Insertion
- Deletion
- Search by key value
- Listing of node keys in order of value (from left to right)
*/
2017-12-27 17:01:50 +03:00
// Node, the basic data structure in the tree
2017-10-14 09:31:40 +03:00
typedef struct node{
// left child
2017-10-14 09:31:40 +03:00
struct node* left;
// right child
2017-10-14 09:31:40 +03:00
struct node* right;
// data of the node
2017-10-14 09:31:40 +03:00
int data;
} node;
2017-12-27 17:01:50 +03:00
// The node constructor, which receives the key value input and returns a node pointer
2017-10-14 09:31:40 +03:00
node* newNode(int data){
// creates a slug
2017-10-14 09:31:40 +03:00
node* tmp = (node*)malloc(sizeof(node));
// initializes the slug
2017-10-14 09:31:40 +03:00
tmp->data = data;
tmp->left = NULL;
tmp->right = NULL;
return tmp;
}
2017-12-27 17:01:50 +03:00
// Insertion procedure, which inserts the input key in a new node in the tree
2017-10-14 09:31:40 +03:00
node* insert(node* root, int data){
2017-12-27 17:01:50 +03:00
// If the root of the subtree is null, insert key here
2017-10-14 09:31:40 +03:00
if (root == NULL)
root = newNode(data);
2017-12-27 17:01:50 +03:00
// If it isn't null and the input key is greater than the root key, insert in the right leaf
2017-10-14 09:31:40 +03:00
else if (data > root->data)
root->right = insert(root->right, data);
2017-12-27 17:01:50 +03:00
// If it isn't null and the input key is lower than the root key, insert in the left leaf
2017-10-14 09:31:40 +03:00
else if (data < root->data)
root->left = insert(root->left, data);
2017-12-27 17:01:50 +03:00
// Returns the modified tree
2017-10-14 09:31:40 +03:00
return root;
}
2017-12-27 17:01:50 +03:00
// Utilitary procedure to find the greatest key in the left subtree
2017-10-14 09:31:40 +03:00
node* getMax(node* root){
2017-12-27 17:01:50 +03:00
// If there's no leaf to the right, then this is the maximum key value
2017-10-14 09:31:40 +03:00
if (root->right == NULL)
return root;
else
root->right = getMax(root->right);
}
2017-12-27 17:01:50 +03:00
// Deletion procedure, which searches for the input key in the tree and removes it if present
2017-10-14 09:31:40 +03:00
node* delete(node* root, int data){
2017-12-27 17:01:50 +03:00
// If the root is null, nothing to be done
if (root == NULL)
2017-10-14 09:31:40 +03:00
return root;
2017-12-27 17:01:50 +03:00
// If the input key is greater than the root's, search in the right subtree
2017-10-14 09:31:40 +03:00
else if (data > root->data)
root->right = delete(root->right, data);
2017-12-27 17:01:50 +03:00
// If the input key is lower than the root's, search in the left subtree
2017-10-14 09:31:40 +03:00
else if (data < root->data)
root->left = delete(root->left, data);
2017-12-27 17:01:50 +03:00
// If the input key matches the root's, check the following cases
// termination condition
2017-10-14 09:31:40 +03:00
else if (data == root->data){
2017-12-27 17:01:50 +03:00
// Case 1: the root has no leaves, remove the node
2017-10-14 09:31:40 +03:00
if ((root->left == NULL) && (root->right == NULL)){
free(root);
return NULL;
}
2017-12-27 17:01:50 +03:00
// Case 2: the root has one leaf, make the leaf the new root and remove the old root
2017-10-14 09:31:40 +03:00
else if (root->left == NULL){
2017-12-27 17:01:50 +03:00
node* tmp = root;
root = root->right;
free(tmp);
return root;
2017-10-14 09:31:40 +03:00
}
else if (root->right == NULL){
2017-12-27 17:01:50 +03:00
node* tmp = root;
root = root->left;
free(tmp);
return root;
2017-10-14 09:31:40 +03:00
}
2017-12-27 17:01:50 +03:00
// Case 3: the root has 2 leaves, find the greatest key in the left subtree and switch with the root's
2017-10-14 09:31:40 +03:00
else {
// finds the biggest node in the left branch.
2017-10-14 09:31:40 +03:00
node* tmp = getMax(root->left);
// sets the data of this node equal to the data of the biggest node (lefts)
2017-10-14 09:31:40 +03:00
root->data = tmp->data;
root->left = delete(root->left, tmp->data);
}
}
return root;
}
2017-12-27 17:01:50 +03:00
// Search procedure, which looks for the input key in the tree and returns 1 if it's present or 0 if it's not in the tree
2017-10-14 09:31:40 +03:00
int find(node* root, int data){
2017-12-27 17:01:50 +03:00
// If the root is null, the key's not present
2017-10-14 09:31:40 +03:00
if (root == NULL)
return 0;
2017-12-27 17:01:50 +03:00
// If the input key is greater than the root's, search in the right subtree
2017-10-14 09:31:40 +03:00
else if (data > root->data)
return find(root->right, data);
2017-12-27 17:01:50 +03:00
// If the input key is lower than the root's, search in the left subtree
2017-10-14 09:31:40 +03:00
else if (data < root->data)
return find(root->left, data);
2017-12-27 17:01:50 +03:00
// If the input and the root key match, return 1
2017-10-14 09:31:40 +03:00
else if (data == root->data)
return 1;
}
2017-12-27 17:01:50 +03:00
// Utilitary procedure to measure the height of the binary tree
2017-10-14 09:31:40 +03:00
int height(node* root){
2017-12-27 17:01:50 +03:00
// If the root is null, this is the bottom of the tree (height 0)
2017-10-14 09:31:40 +03:00
if (root == NULL)
return 0;
else{
2017-12-27 17:01:50 +03:00
// Get the height from both left and right subtrees to check which is the greatest
2017-10-14 09:31:40 +03:00
int right_h = height(root->right);
int left_h = height(root->left);
2017-12-27 17:01:50 +03:00
// The final height is the height of the greatest subtree(left or right) plus 1(which is the root's level)
2017-10-14 09:31:40 +03:00
if (right_h > left_h)
return (right_h + 1);
else
return (left_h + 1);
}
}
2017-12-27 17:01:50 +03:00
// Utilitary procedure to free all nodes in a tree
2017-10-14 09:31:40 +03:00
void purge(node* root){
if (root != NULL){
if (root->left != NULL)
purge(root->left);
if (root->right != NULL)
purge(root->right);
free(root);
}
}
2017-12-27 17:01:50 +03:00
// Traversal procedure to list the current keys in the tree in order of value (from the left to the right)
2017-10-14 09:31:40 +03:00
void inOrder(node* root){
if(root != NULL){
inOrder(root->left);
printf("\t[ %d ]\t", root->data);
inOrder(root->right);
}
}
void main(){
// this reference don't change.
// only the tree changes.
2017-10-14 09:31:40 +03:00
node* root = NULL;
int opt = -1;
int data = 0;
2017-10-14 09:31:40 +03:00
// event-loop.
2017-10-14 09:31:40 +03:00
while (opt != 0){
printf("\n\n[1] Insert Node\n[2] Delete Node\n[3] Find a Node\n[4] Get current Height\n[5] Print Tree in Crescent Order\n[0] Quit\n");
scanf("%d",&opt); // reads the choice of the user
2017-10-14 09:31:40 +03:00
// processes the choice
2017-10-14 09:31:40 +03:00
switch(opt){
case 1: printf("Enter the new node's value:\n");
scanf("%d",&data);
root = insert(root,data);
break;
case 2: printf("Enter the value to be removed:\n");
if (root != NULL){
scanf("%d",&data);
root = delete(root,data);
}
else
2017-10-14 09:31:40 +03:00
printf("Tree is already empty!\n");
break;
case 3: printf("Enter the searched value:\n");
scanf("%d",&data);
find(root,data) ? printf("The value is in the tree.\n") : printf("The value is not in the tree.\n");
break;
2017-10-14 09:31:40 +03:00
case 4: printf("Current height of the tree is: %d\n", height(root));
break;
case 5: inOrder(root);
break;
}
}
// deletes the tree from the heap.
2017-10-14 09:31:40 +03:00
purge(root);
}