mirror of
https://github.moeyy.xyz/https://github.com/TheAlgorithms/C.git
synced 2023-10-11 15:56:24 +08:00
Update binary_search_tree.c
This commit is contained in:
parent
aef7477934
commit
0261e53734
@ -1,12 +1,21 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Node, the basic data structure in the tree
|
||||||
typedef struct node{
|
typedef struct node{
|
||||||
struct node* left;
|
struct node* left;
|
||||||
struct node* right;
|
struct node* right;
|
||||||
int data;
|
int data;
|
||||||
} node;
|
} node;
|
||||||
|
|
||||||
|
// The node constructor, which receives the key value input and returns a node pointer
|
||||||
node* newNode(int data){
|
node* newNode(int data){
|
||||||
node* tmp = (node*)malloc(sizeof(node));
|
node* tmp = (node*)malloc(sizeof(node));
|
||||||
tmp->data = data;
|
tmp->data = data;
|
||||||
@ -16,51 +25,62 @@ node* newNode(int data){
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insertion procedure, which inserts the input key in a new node in the tree
|
||||||
node* insert(node* root, int data){
|
node* insert(node* root, int data){
|
||||||
|
// If the root of the subtree is null, insert key here
|
||||||
if (root == NULL)
|
if (root == NULL)
|
||||||
root = newNode(data);
|
root = newNode(data);
|
||||||
|
// If it isn't null and the input key is greater than the root key, insert in the right leaf
|
||||||
else if (data > root->data)
|
else if (data > root->data)
|
||||||
root->right = insert(root->right, data);
|
root->right = insert(root->right, data);
|
||||||
|
// If it isn't null and the input key is lower than the root key, insert in the left leaf
|
||||||
else if (data < root->data)
|
else if (data < root->data)
|
||||||
root->left = insert(root->left, data);
|
root->left = insert(root->left, data);
|
||||||
|
// Returns the modified tree
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utilitary procedure to find the greatest key in the left subtree
|
||||||
node* getMax(node* root){
|
node* getMax(node* root){
|
||||||
|
// If there's no leaf to the right, then this is the maximum key value
|
||||||
if (root->right == NULL)
|
if (root->right == NULL)
|
||||||
return root;
|
return root;
|
||||||
else
|
else
|
||||||
root->right = getMax(root->right);
|
root->right = getMax(root->right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deletion procedure, which searches for the input key in the tree and removes it if present
|
||||||
node* delete(node* root, int data){
|
node* delete(node* root, int data){
|
||||||
|
// If the root is null, nothing to be done
|
||||||
if (root == NULL)
|
if (root == NULL)
|
||||||
return root;
|
return root;
|
||||||
|
// If the input key is greater than the root's, search in the right subtree
|
||||||
else if (data > root->data)
|
else if (data > root->data)
|
||||||
root->right = delete(root->right, data);
|
root->right = delete(root->right, data);
|
||||||
|
// If the input key is lower than the root's, search in the left subtree
|
||||||
else if (data < root->data)
|
else if (data < root->data)
|
||||||
root->left = delete(root->left, data);
|
root->left = delete(root->left, data);
|
||||||
|
// If the input key matches the root's, check the following cases
|
||||||
else if (data == root->data){
|
else if (data == root->data){
|
||||||
|
// Case 1: the root has no leaves, remove the node
|
||||||
if ((root->left == NULL) && (root->right == NULL)){
|
if ((root->left == NULL) && (root->right == NULL)){
|
||||||
free(root);
|
free(root);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// Case 2: the root has one leaf, make the leaf the new root and remove the old root
|
||||||
else if (root->left == NULL){
|
else if (root->left == NULL){
|
||||||
node* tmp = root->right;
|
node* tmp = root;
|
||||||
free(root);
|
root = root->right;
|
||||||
return tmp;
|
free(tmp);
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
else if (root->right == NULL){
|
else if (root->right == NULL){
|
||||||
node* tmp = root->left;
|
node* tmp = root;
|
||||||
free(root);
|
root = root->left;
|
||||||
return tmp;
|
free(tmp);
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
|
// Case 3: the root has 2 leaves, find the greatest key in the left subtree and switch with the root's
|
||||||
else {
|
else {
|
||||||
node* tmp = getMax(root->left);
|
node* tmp = getMax(root->left);
|
||||||
root->data = tmp->data;
|
root->data = tmp->data;
|
||||||
@ -70,24 +90,33 @@ node* delete(node* root, int data){
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
int find(node* root, int data){
|
int find(node* root, int data){
|
||||||
|
// If the root is null, the key's not present
|
||||||
if (root == NULL)
|
if (root == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
// If the input key is greater than the root's, search in the right subtree
|
||||||
else if (data > root->data)
|
else if (data > root->data)
|
||||||
return find(root->right, data);
|
return find(root->right, data);
|
||||||
|
// If the input key is lower than the root's, search in the left subtree
|
||||||
else if (data < root->data)
|
else if (data < root->data)
|
||||||
return find(root->left, data);
|
return find(root->left, data);
|
||||||
|
// If the input and the root key match, return 1
|
||||||
else if (data == root->data)
|
else if (data == root->data)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utilitary procedure to measure the height of the binary tree
|
||||||
int height(node* root){
|
int height(node* root){
|
||||||
|
// If the root is null, this is the bottom of the tree (height 0)
|
||||||
if (root == NULL)
|
if (root == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
else{
|
else{
|
||||||
|
// Get the height from both left and right subtrees to check which is the greatest
|
||||||
int right_h = height(root->right);
|
int right_h = height(root->right);
|
||||||
int left_h = height(root->left);
|
int left_h = height(root->left);
|
||||||
|
|
||||||
|
// The final height is the height of the greatest subtree(left or right) plus 1(which is the root's level)
|
||||||
if (right_h > left_h)
|
if (right_h > left_h)
|
||||||
return (right_h + 1);
|
return (right_h + 1);
|
||||||
else
|
else
|
||||||
@ -95,6 +124,7 @@ int height(node* root){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utilitary procedure to free all nodes in a tree
|
||||||
void purge(node* root){
|
void purge(node* root){
|
||||||
if (root != NULL){
|
if (root != NULL){
|
||||||
if (root->left != NULL)
|
if (root->left != NULL)
|
||||||
@ -105,6 +135,7 @@ void purge(node* root){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Traversal procedure to list the current keys in the tree in order of value (from the left to the right)
|
||||||
void inOrder(node* root){
|
void inOrder(node* root){
|
||||||
if(root != NULL){
|
if(root != NULL){
|
||||||
inOrder(root->left);
|
inOrder(root->left);
|
||||||
|
Loading…
Reference in New Issue
Block a user