Deleting a node with 2 children from a binary search tree - c

I am trying to delete a node having 2 chidren in a binary search tree. However i am facing little problem here. While deleting node(node with data=30) with children (left->data=20,right->data=40), I am replacing the node with its inorder successor (which is node with data=40) and then deleting the inorder successor. After deletion the node's data is successfully replaced (new value being 40) but the inorder successor is not being deleted/freed properly.
Expected Output [inorder traversal]: 20->40->50->60->70->80->
Output[inorder traversal]: 20->40->0->50->60->70->80->
After 40, why is the value 0 appearing?
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *left;
struct Node *right;
};
struct Node* temp = NULL,*temp1 = NULL;
struct Node *newNode(int data)
{
struct Node *node = (struct Node*)malloc(sizeof(struct Node));
node->data = data;
node->left = node->right = NULL;
return node;
}
struct Node* insert(struct Node* root,int data)
{
if(root == NULL)
{
return newNode(data);
}
if(data < root->data)
root->left = insert(root->left,data);
else
root->right = insert(root->right,data);
}
void inorder(struct Node* root)
{
if(root!=NULL)
{
inorder(root->left);
printf("%d->",root->data);
inorder(root->right);
}
else
{
return;
}
}
/*to find the inorder successor*/
struct Node *minVal(struct Node *root)
{
while(root->left !=NULL)
{
temp = root;
root = root->left;
}
return root;
}
void deleteNode(struct Node *root,int data)
{
if(data < root->data)
{
temp = root;
deleteNode(root->left,data);
}
else if(data > root->data)
{
temp = root;
deleteNode(root->right,data);
}
else if(data == root->data)
{ /*deleting leaf nodes*/
if(root->left == NULL && root->right == NULL)
{
if(temp->left == root)
temp->left = NULL;
else
if(temp->right == root)
temp->right = NULL;
free(root);
root = NULL;
return;
}
/*deleting nodes having single child*/
else if(root->left !=NULL && root->right == NULL)
{
temp1 = root->left;
temp->left = temp1;
free(root);
root = NULL;
}
else if(root->left ==NULL && root->right != NULL)
{
temp1 = root->right;
temp->right = temp1;
free(root);
root = NULL;
}
/*deleting nodes having 2 children*/
else if(root->left !=NULL && root->right !=NULL)
{
struct Node *temp2 = minVal(root->right);
root->data = temp2->data;
deleteNode(root->right,temp2->data);
}
}
}
int main()
{
struct Node *root = NULL;
printf("\n\n");
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
inorder(root);
//deleteNode(root,40);
deleteNode(root,30);
printf("\n\n");
inorder(root);
printf("\n\n");
}

Related

BST - Deleting a Node

so I'm trying to solve a problem from log2base2.com involving deleting a node from BST. It works except when trying to delete a node with two children. I know I could simply replace the numbers and then delete the duplicate at the end, but what if my struct has more data than just key? So what am I doing wrong please?
#include<stdio.h>
#include<stdlib.h>
struct node
{
int key;
struct node *left;
struct node *right;
};
int getRightMin(struct node *root)
{
//Write your code here
struct node *temp = root;
while(temp->left!=NULL)
{
temp=temp->left;
}
return temp;
}
struct node *removeNode(struct node *root, int key)
{
//Write your code here
if(root == NULL){return NULL;}
if(key<root->key){root->left = removeNode(root->left, key);}
else if(key>root->key){root->right = removeNode(root->right,key);}
else
{
if(root->left==NULL && root->right==NULL)
{
free(root);
return NULL;
}
else if(root->left)
{
struct node *temp = root->left;
free(root);
return temp;
}
else if(root->right)
{
struct node *temp = root->right;
free(root);
return temp;
}
else
{
struct node *temp = getRightMin(root->right);
temp->left = root->left;
temp->right = root->right;
root = temp;
root->right = removeNode(root->right, temp->key);
}
}
return root;
}
//Don't change the below code
struct node *getNewNode(int val)
{
struct node *newNode = malloc(sizeof(struct node));
newNode->key = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
struct node *insert(struct node *root, int val)
{
if(root == NULL)
return getNewNode(val);
if(root->key < val)
root->right = insert(root->right,val);
else if(root->key > val)
root->left = insert(root->left,val);
return root;
}
void inorder(struct node *root)
{
if(root == NULL)
return;
inorder(root->left);
printf("%d ",root->key);
inorder(root->right);
}
int main()
{
struct node *root = NULL;
root = insert(root,100);
root = insert(root,50);
root = insert(root,200);
root = insert(root,150);
root = insert(root,300);
int key;
scanf("%d",&key);
root = removeNode(root,key);
inorder(root);
return 0;
}
TEST CASE 1:
INPUT: 200
EXPECTED OUTPUT: 50 100 150 300
ACTUAL OUTPUT: 50 100 150
TEST CASE 2:
INPUT: 100
EXPECTED OUTPUT: 50 150 200 300
ACTUAL OUTPUT: 50
You have to reorder conditional in removeNode() to:
if(root->left==NULL && root->right==NULL)
{
free(root);
return NULL;
}
else if (root->left && root->right)
{
struct node *temp = getRightMin(root->right);
temp->left = root->left;
temp->right = root->right;
root = temp;
root->right = removeNode(root->right, temp->key);
}
else if(root->left)
{
struct node *temp = root->left;
free(root);
return temp;
}
else // root->right != NULL
{
struct node *temp = root->right;
free(root);
return temp;
}
It looks that (root->left && root->right) case was caught by (root->left) and
reference to root->right was lost.

Issue while removing elements in Binary Search Tree

When I remove the nodes which have zero children, it removes the entire branch starting from the head i.e. if I remove a leaf node from the right subtree, it removes the right branch and same for the left.
If I remove any child with 2 children, it replaces it with the leftmost node of the right subtree and then removes the entire right branch from where I am taking the leftmost node.
struct Node{
struct Node *left;
int value;
struct Node *right;
};
typedef struct Node node;
node * removeEle(node **root, int value){
if((*root) == NULL){
return NULL;
}else{
if(value < (*root)->value && (*root)->left != NULL){
(*root)->left = removeEle(&(*root)->left, value);
}else if(value > (*root)->value && (*root)->right != NULL){
(*root)->right = removeEle(&(*root)->right, value);
}else{
if((*root)->left == NULL && (*root)->right == NULL){
return NULL;
}else if((*root)->left == NULL && (*root)->right != NULL){
return (*root)->right;
}else if((*root)->left != NULL && (*root)->right == NULL){
return (*root)->left;
}
else{
node * check = leftMost(&(*root)->right);
(*root)->value = check->value;
(*root)->right = removeEle(&(*root)->right, check->value);
return (*root);
}
}
if((*root) == NULL){
printf("Helloworld");
exit(1);
}
}
}
node * leftMost(node **root){
while((*root)->left != NULL){
(*root) = (*root)->left;
}
return (*root);
}
void traversal(node *root){
if(root == NULL)return;
printf("%d\n", root->value);
if(root->left != NULL) traversal(root->left);
if(root->right != NULL) traversal(root->right);
}
void add(node **root, int value){
if((*root) == NULL){
(*root) = createNode();
(*root)->value = value;
}
if((*root)->value > value){
if((*root)->left == NULL){
(*root)->left = createNode();
(*root)->left->value = value;
}else{
add(&((*root)->left), value);
}
}else if((*root)->value < value){
if((*root)->right == NULL){
(*root)->right = createNode();
(*root)->right->value = value;
}else{
add(&((*root)->right), value);
}
}
}
node *createNode(){
node *node = malloc(sizeof(struct Node));
node->left = NULL;
node->right = NULL;
return node;
}
This is my test case.
int main(){
node *root = NULL;
add(&root, 10);
add(&root, 20);
add(&root, 5);
add(&root, 6);
add(&root, 2);
add(&root, 23);
add(&root, 12);
removeEle(&root, 10);
traversal(root);
}
All the functions except removal, works fine.

View AVL tree not giving the correct output

I am working on a school project that involves implementing an AVL Tree with the functions to insert delete and view. But my program didnt give the correct output when viewing the avl tree with preorder traversal.
The variable for avl tree:
typedef struct Node{
int data;
int height;
struct Node *right;
struct Node *left;
}Node;
Here is my insert function with newnode function call:
Node *newNode(int data){
Node *node = (Node*)malloc(sizeof(Node));
node->data = data;
node->left = NULL;
node->right = NULL;
node->height = 1;
return(node);
}
Node *insertNode(Node *node, int data){
if(node == NULL)
return(newNode(data));
if(data < node->data)
node->left = insertNode(node->left, data);
if(data > node->data)
node->right = insertNode(node->right, data);
if(data == node->data){
printf("No duplicate allowed.");
return node;
}
node->height = getHeight(node);
return(balancing(node, data));
}
Delete function with minvaluenode function call:
Node * minValueNode(Node* node){
Node* current = node;
while (current->left != NULL)
current = current->left;
return current;
}
Node *deleteNode(Node *root, int data){
if(root == NULL){
printf("Value not found.");
return root;
}
else if ( data < root->data )
root->left = deleteNode(root->left, data);
else if( data > root->data )
root->right = deleteNode(root->right, data);
else if(data == root->data){
if( (root->left == NULL) || (root->right == NULL) ){
Node *temp = root->left ? root->left : root->right;
if (temp == NULL){
temp = root;
root = NULL;
}
else
*root = *temp;
free(temp);
}
else{
Node* temp = minValueNode(root->right);
root->data = temp->data;
root->right = deleteNode(root->right,temp->data);
}
}
if(root == NULL)
return root;
root->height = getHeight(root);
return(balancing(root, data));
}
Balancing function with rotate,getbalancefactor, max, and getheight function calls:
int max(int number1, int number2){
return (number1 > number2) ? number1 : number2;
}
int getHeight(Node* n) {
return max(height(n->left), height(n->right)) + 1;
}
int getBalanceFactor(Node *currentNode){
if(currentNode == NULL)
return 0;
return height(currentNode->left) - height(currentNode->right);
}
Node *rightRotate(Node *currentNode){
Node *temp = currentNode->left;
currentNode->left = temp->right;
temp->right = currentNode;
temp->height = getHeight(temp);
currentNode->height = getHeight(currentNode);
return temp;
}
Node *leftRotate(Node *currentNode){
Node *temp = currentNode->right;
currentNode->right = temp->left;
temp->left = currentNode;
temp->height = getHeight(temp);
currentNode->height = getHeight(currentNode);
return temp;
}
Node *balancing(Node *node, int data){
if(getBalanceFactor(node) >= 2 && data < node->left->data)
return rightRotate(node);
if(getBalanceFactor(node) <= -2 && data > node->right->data)
return leftRotate(node);
if(getBalanceFactor(node) >= 2 && data > node->left->data){
node->left = leftRotate(node->left);
return(rightRotate(node));
}
if(getBalanceFactor(node) <= -2 && data < node->right->data){
node->right = rightRotate(node->right);
return(leftRotate(node));
}
return node;
}
My view function:
//print AVL Tree in preorder traversal
void printAVLTree(Node *root){
if(root != NULL)
{
printf("%d ", root->data);
printAVLTree(root->left);
printAVLTree(root->right);
}
}
I made a test with random insert input:
9 5 10 6 0 11 -1 1 2
The output when calling the view function is:
5 1 0 -1 2 9 6 10 11
The correct output should be:
9 1 0 -1 5 2 6 10 11
Your mistake is that you are updating the height values in the wrong order (top to bottom):
temp->height = getHeight(temp);
currentNode->height = getHeight(currentNode);
After rotation, the lower node is currentNode so you have to update it first.
Otherwise, if you update temp before updating currentNode, temp will use the previous value of currentNode height and will have a wrong height

Deletion of node in Binary Search Tree is throwing error

Experts, this is my code of creation and deletion of nodes in Binary Search Tree. It's working fine for insertion, but throwing segmentation fault (core dumped) when trying to delete a node (on invoking deleteNode( ) function). I don't understand what's actually the problem. Please help! Thank you in advance!
#include <stdio.h>
#include <stdlib.h>
int size = 0;
typedef struct mylist{
int data;
struct mylist *left;
struct mylist *right;
}node;
node *root;
void create_root(node *root){
root = NULL;
}
//Inserting nodes
node* insert(node *root, int val){
node *ptr, *parentptr, *nodeptr;
ptr = (node*)malloc(sizeof(node));
ptr -> data = val;
ptr -> left = NULL;
ptr -> right = NULL;
if(root == NULL)
root = ptr;
else{
parentptr = NULL;
nodeptr = root;
while(nodeptr != NULL){
parentptr=nodeptr;
if(val < nodeptr -> data)
nodeptr = nodeptr -> left;
else
nodeptr = nodeptr -> right;
}
if(val < parentptr -> data)
parentptr -> left = ptr;
else
parentptr -> right = ptr;
}
return root;
}
node* minValueNode(node* root)
{
node* cur = root;
while (cur->left != NULL)
cur = cur->left;
return cur;
}
node* deleteNode(node* root, int key)
{
if (root == NULL){
printf("\nValue not found\n");
}
if (key < root-> data)
root->left = deleteNode(root->left, key);
else if (key > root-> data)
root->right = deleteNode(root->right, key);
else
{
if (root->left == NULL)
{
node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
node *temp = root->left;
free(root);
return temp;
}
node* temp = minValueNode(root->right); //Inorder successor
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
void main(){
int option, val;
node *ptr;
int flag = 1;
create_root(root);
while(flag != 2){
printf("\nChoose-\n1-Insert\n2-Delete\n3-Exit\n");
scanf("%d", &option);
switch(option){
case 1:{
printf("\nEnter the value of new node\n");
size++;
scanf("%d", &val);
root = insert(root, val);
break;
}
case 2:{
int k;
printf("Enter the value to delete");
scanf("%d",&k);
root=deleteNode(root, k);
size--;
break;
}
case 3:
flag=2;
break;
default:
printf("\nWrong entry\n");
}
}
}
You must either return NULL in the first if() in deleteNode(), or you must put an else before the second if()
node* deleteNode(node* root, int key)
{
if (root == NULL){
printf("\nValue not found\n");
return NULL; // <== This was missing.
}
...
}
or alternatively (perhaps intended?):
node* deleteNode(node* root, int key)
{
if (root == NULL){
printf("\nValue not found\n");
}
else if(key < root->data)
...
}
At the moment this falls through to the next if(key < root->data) even when root is null, which causes the segfault.
Also: Use nullptr if you can use C++11.

Delete function in Binary Tree in C

I'm writing the basic functions for binary tree and everything seems to compile and run, but when i try to use my delete function it doesn't do anything.
After executing i get the same sequence of numbers, so i'm trying to figure out what's wrong with the Delete function, is it logically correct?
#include <stdio.h>
#include <stdlib.h>
typedef struct treeNode
{
int data;
struct treeNode *left;
struct treeNode *right;
}treeNode;
treeNode *Insert(treeNode *node, int data)
{
if(node == NULL)
{
treeNode *temp;
temp = malloc(sizeof(treeNode));
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
if(data > (node->data))
{
node->right = Insert(node->right, data);
}
else if(data < (node->data))
{
node->left = Insert(node->left, data);
}
return node;
}
treeNode *Delete(treeNode *node, int data)
{
if(node == NULL)
{
printf("element not found\n");
}
else if(data < node->data)
{
node->left = Delete(node->left, data);
}
else if(data > node->data)
{
node->right = Delete(node->right, data);
}
return node;
}
treeNode *Find(treeNode *node, int data)
{
if(node == NULL)
{
return NULL;
}
if(data > node->data)
{
return Find(node->right, data);
}
else if(data < node->data)
{
return Find(node->left, data);
}
else
{
return node;
}
}
void Print(treeNode *node)
{
if(node == NULL)
{
return;
}
Print(node->left);
printf("%d", node->data);
Print(node->right);
}
int main()
{
treeNode *root = NULL;
root = Insert(root, 5);
root = Insert(root, 8);
root = Insert(root, 6);
root = Insert(root, 4);
root = Insert(root, 3);
root = Insert(root, 9);
root = Insert(root, 10);
root = Insert(root, 19);
Print(root);
printf("\n");
root = Delete(root, 5);
root = Delete(root, 8);
Print(root);
printf("\n");
treeNode *temp;
temp = Find(root, 8);
if(temp == NULL)
{
printf("Element 8 not found\n");
}
else
{
printf("Element 8 found\n");
}
temp = Find(root, 5);
if(temp == NULL)
{
printf("element 5 not found\n");
}
else
{
printf("element 5 found\n");
}
}
Basically i was only replacing the node with itself, but this can be solved by replacing the deleted node with the minimum element in the right subtree or the maximum element in the left subtree.
The function that works:
treeNode * Delete(treeNode *node, int data)
{
treeNode *temp;
if(node==NULL)
{
printf("Element Not Found");
}
else if(data < node->data)
{
node->left = Delete(node->left, data);
}
else if(data > node->data)
{
node->right = Delete(node->right, data);
}
else
{
/* Now We can delete this node and replace with either minimum element
in the right sub tree or maximum element in the left subtree*/
if(node->right && node->left)
{
/* Here we will replace with minimum element in the right sub tree */
temp = FindMin(node->right);
node -> data = temp->data;
/* As we replaced it with some other node, we have to delete that node */
node -> right = Delete(node->right,temp->data);
}
else
{
/* If there is only one or zero children then we can directly
remove it from the tree and connect its parent to its child */
temp = node;
if(node->left == NULL)
node = node->right;
else if(node->right == NULL)
node = node->left;
free(temp); /* temp is longer required */
}
}
return node;
}

Resources