Delete function in Binary Tree in C - 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;
}

Related

Stuck at deleting node from Binary Search Tree

I have been trying to follow the textbook "Introduction to Algorithms" but I'm stuck at the following step when deleting a node from a BST - when the node to be deleted has both children
My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bst.h"
void error()
{
fprintf(stderr, "%s\n", "Error assigning memory to node");
exit(1);
}
void insert(node **root, int key)
{
node *t1, *t2;
if (*root == NULL) {
printf("Root is null\n");
*root = (node *)malloc(sizeof(node));
if (*root==NULL) {
fprintf(stderr, "%s\n", "Cannot allocate memory for node in Insert");
exit(1);
}
(*root)->key = key;
(*root)->left = (*root)->right = NULL;
}
else {
printf("Root contains data. Inserting new node.\n");
t1 = *root;
while (t1 != NULL) {
t2 = t1;
if (key < t1->key)
t1 = t1->left;
else
t1 = t1->right;
}
if(key < t2->key) {
t2->left = (node *) malloc(sizeof(node));
t2 = t2->left;
if (t2==NULL)
error();
t2 -> key = key;
}
else {
t2->right = (node *) malloc(sizeof(node));
t2 = t2->right;
if (t2==NULL)
error();
t2->key = key;
}
}
}
void inorder(node * root)
{
if (root!=NULL) {
inorder(root->left);
printf("%d ->", root->key);
inorder(root->right);
}
}
node * search(node *root, int key)
{
node * t = root;
while (t!=NULL)
{
if (key == t->key)
return t;
else if (key < t->key)
t = t->left;
else
t = t->right;
}
return NULL;
}
node * getparent(node * root, int key)
{
node * t = root, *parent = NULL;
while (t!=NULL)
{
if (key == t->key)
return parent;
else if (key < t->key)
t = t->left;
else
t = t->right;
parent = t;
}
return NULL;
}
node * delete(node *root, int key)
{
node * todelete = search(root,key), *parent = getparent(root, key), *y;
if (todelete==NULL) {
fprintf(stderr, "%s\n", "Key not found");
exit(2);
}
if (todelete->left == NULL && todelete->right==NULL) { //Deleting node with no children
if (todelete == parent->left)
parent->left = NULL;
else
parent->right = NULL;
free(todelete);
return root;
}
else if (todelete->left && !todelete->right) {
if (todelete == parent->left)
parent->left = todelete->left;
else
parent->right = todelete->right;
free(todelete);
return root;
}
else if (todelete->right & !todelete->left) {
if (todelete == parent->left)
parent->left = todelete->left;
else
parent->right = todelete->right;
free(todelete);
return root;
}
else
{
node * yparent = NULL;
y= todelete->right;
while (y->left!=NULL)
{
y = y->left;
yparent = y;
}
if(yparent != todelete) {
//stuck here
}
}
}
bst.h:
struct treenode
{
int key;
struct treenode *left;
struct treenode *right;
};
typedef struct treenode node;
node * getparent(node * root, int key);
void insert(node **root, int key);
node * search(node *root, int key);
node * delete(node *root, int key);
void inorder(node * root);
Any guidance would be much appreciated. I should be trying to set the y = y->right and then set todelete->right = y correct?
I'm stuck at the following step when deleting a node from a BST - when the node to be deleted has both children
It follows from the properties of a BST that if a node N has two children then every node in the subtree rooted at the left child is less than every node in the subtree rooted at the right child and vise versa. In particular, the largest node in the left subtree, Lmax, is less than all the nodes in the right subtree, and the least node in the right subtree, Rmin, is larger than all the nodes of the left subtree. These are the nodes immediately preceding and following N in an in-order traversal. Both of those descendants are easy to find, and neither has more than one child (else they could neither be max nor min in any subtree).
It follows, then, that if you want to delete node N then you may choose either Lmax or Rmin, delete it from the tree (which is easy because it has at most one child), and replace N with it. Alternatively, delete Lmax or Rmin, and replace the key of node N with the key of that deleted node.
Changed the code to the following and it works (for the delete functions):
static void transplant(node * root, node * u, node * v)
{
node *uparent = getparent(root, u->key);
node * vparent = getparent(root, v->key);
if (uparent == NULL)
root = v;
else if (u == uparent->left)
uparent->left = v;
else uparent->right = v;
if (v!=NULL)
vparent = uparent;
}
node * delete(node *root, int key)
{
node * todelete = search(root,key), *parent = getparent(root, key), *y;
if (todelete==NULL) {
fprintf(stderr, "%s\n", "Key not found");
exit(2);
}
if (todelete->left == NULL && todelete->right==NULL) { //Deleting node with no children
if (todelete == parent->left)
parent->left = NULL;
else
parent->right = NULL;
free(todelete);
return root;
}
else if (todelete->left && !todelete->right) {
if (todelete == parent->left)
parent->left = todelete->left;
else
parent->right = todelete->left;
free(todelete);
return root;
}
else if (todelete->right && !todelete->left) {
if (todelete == parent->left)
parent->left = todelete->right;
else
parent->right = todelete->right;
free(todelete);
return root;
}
else {
y = todelete->right;
while(y->left!=NULL)
{
y = y->left;
}
node *yparent = getparent(root, y->key);
if (yparent != todelete)
{
transplant(root, y, y->right);
y->right = todelete->right;
node * yrightparent = getparent(root, y->right->key);
yrightparent = y;
}
transplant(root, todelete, y);
y->left = todelete->left;
node *yleftparent = getparent(root, y->left->key);
yleftparent = y;
free(todelete);
return root;
}

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.

Deleting a node with 2 children from a binary search tree

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");
}

Deleting a node from a binary search tree without recursion

I have a binary search tree. I want to delete a node from it:
void deleteANode(struct node *head, int value) {
//let us find the node
struct node *temp = head;
struct node *parent = NULL;
//let us find the node
while (temp != NULL) {
if (value > temp->data) {
parent = temp;
temp = temp->right;
} else
if (value < temp->data) {
parent = temp;
temp = temp->left;
} else {
//let us check for child nodes
//
if (temp->left == NULL && temp->right == NULL) {
printf("Deleting a leaf.\n");
temp = NULL;
printf("Set temp null.\n");
free(temp);
break;
} else
if (temp->left == NULL || temp->right == NULL) {
printf("Deleting a one child.\n");
//one of the child is null
if (temp->left != NULL) {
parent->left = temp->left;
} else {
parent->right = temp->right;
}
free(temp);
} else {
printf("Deleting two child parent.\n");
//both of them are not NULL
//need to find the pre-order successor
struct node *temp2 = temp->right;
while (temp2->left != NULL) {
temp2 = temp2->left;
}
//found the successor.
temp->data = temp2->data;
free(temp);
}
break;
}
}
}
I am trying to delete a leaf node in this block:
if (temp->left == NULL && temp->right == NULL) {
printf("Deleting a leaf.\n");
temp->data = NULL;
printf("Set temp null.\n");
free(temp);
break;
}
But the above code doesn't work.
I am calling the above method:
deleteANode(head, 3);
The preorder traversal is remains same before and after:
5 4 3 10 7 20 Deleting a leaf. Set temp null.
=============== 5 4 3 10 7 20
What am I doing wrong.
Updated as per #pstrjds comments:
if (temp->left == NULL && temp->right == NULL ) {
printf("Deleting a leaf.\n");
parent->left = NULL;
parent->right = NULL;
free(temp);
temp = NULL;
printf("Set temp null.\n");
break;
}
It's working fine for leaf node. Need to work for node with two children.
In the block of code which is deleting a leaf you are not actually freeing the node nor are you updating the parent node to no longer point to it.
if ( temp -> left == NULL && temp -> right == NULL )
{
printf("Deleting a leaf.\n");
if (parent->left == temp)
{
parent->left = NULL;
}
else
{
parent->right = NULL;
}
free(temp);
temp = NULL;
printf("Set temp null.\n");
break;
}
You could actually remove the line temp = NULL and change the break; to a return statement.
Does your code really work?
It should be like this:
printf("Deleting two child parent.\n");
Node* temp2 = temp->right;
while(temp2->left != NULL)
{
parent = temp2;
temp2 = temp2->left;
}
temp->data = temp2->data;
parent->left = NULL;
delete temp2;
return;
Java Solution
// Java program to demonstrate delete operation in binary search tree
class BinarySearchTree
{
/* Class containing left and right child of current node and key value*/
class Node
{
int key;
Node left, right;
public Node(int item)
{
key = item;
left = right = null;
}
}
// Root of BST
Node root;
// Constructor
BinarySearchTree()
{
root = null;
}
// This method mainly calls deleteRec()
void deleteKey(int key)
{
root = deleteRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node deleteRec(Node root, int key)
{ Node x=root;
Node parent =null;
/* Base Case: If the tree is empty */
while(x!=null)
{
if(x.key>key)
{ parent=x;
x=x.left;
}
else if(x.key<key)
{parent=x;
x=x.right;
}
else
{
if(x.left==null&&x.right==null)
{
System.out.println(x.key+"y1");
if(parent.left==x)
parent.left=null;
else if(parent.right==x)
parent.right=null;
x=null;
break;
}
else
{
System.out.println(x.key+"y2");
if(x.left==null)
{
if(parent.right==x)
parent.right=x.right;
else if(parent.left==x)
parent.left=x.right;
System.out.println(x.key+"yes");
x=null;
break;
}
else if(x.right==null)
{
if(parent.left==x)
parent.left=x.left;
else if(parent.right==x)
parent.right=x.left;
x=null;
break;
}
else
{
Node temp=x;
Node px=null;
temp=temp.right;
while(temp.left!=null)
{ px=temp;
temp=temp.left;
}
x.key=temp.key;
if(px.left==temp)
px.left=null;
else if(px.left==temp)
px.right=null;
temp=null;
break;
}
}
}
}
return root;
}
int minValue(Node root)
{
int minv = root.key;
while (root.left != null)
{
minv = root.left.key;
root = root.left;
}
return minv;
}
// This method mainly calls insertRec()
void insert(int key)
{
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key)
{
/* If the tree is empty, return a new node */
if (root == null)
{
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
// This method mainly calls InorderRec()
void inorder()
{
inorderRec(root);
}
// A utility function to do inorder traversal of BST
void inorderRec(Node root)
{
if (root != null)
{
inorderRec(root.left);
System.out.print(root.key + " ");
inorderRec(root.right);
}
}
// Driver Program to test above functions
public static void main(String[] args)
{
BinarySearchTree tree = new BinarySearchTree();
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80 */
tree.insert(50);
tree.insert(30);
tree.insert(20);
tree.insert(40);
tree.insert(70);
tree.insert(60);
tree.insert(80);
System.out.println("Inorder traversal of the given tree");
tree.inorder();
System.out.println("\nDelete 20");
tree.deleteKey(20);
System.out.println("Inorder traversal of the modified tree");
tree.inorder();
System.out.println("\nDelete 30");
tree.deleteKey(30);
System.out.println("Inorder traversal of the modified tree");
tree.inorder();
System.out.println("\nDelete 50");
tree.deleteKey(50);
System.out.println("Inorder traversal of the modified tree");
tree.inorder();
}
}

Nonrecursive/Iterative Binary Search Tree in C (Homework)

How can I create/delete a node in a Binary Search Tree using Iterative Algorithm in C?
Iterative insertion:
struct tree_node *Insert_Element (struct tree_node *root, void *key, void *data) {
struct tree_node *new_node, *node;
node = root;
do {
switch (compare(key, node->key)) {
case -1: {
if (node->left == NULL) {
if ((new_node = create_node(key, data)) == NULL) {
return NULL;
}
node->left = new_node;
return new_node;
}
node = node->left;
} break;
case 1: {
if (node->right == NULL) {
if ((new_node = create_node(key, data)) == NULL) {
return NULL;
}
node->right = new_node;
return new_node;
}
node = node->right;
} break;
default: {
return node;
}
}
} while (node != NULL);
return NULL;
}
Iterative insertion & deletion in BST
struct bst {
int data;
struct bst *left;
struct bst *right;
};
typedef struct bst bst_t;
bst_t *get_new_node(int val)
{
bst_t *node = (bst_t *) malloc(sizeof(bst_t));
node->data = val;
node->left = NULL;
node->right= NULL;
return node;
}
bst_t *insert(bst_t *root, int val)
{
if(!root) return get_new_node(val);
bst_t *prev = NULL, *ptr = root;
char type = ' ';
while(ptr) {
prev = ptr;
if(val < ptr->data) {
ptr = ptr->left;
type = 'l';
} else {
ptr = ptr->right;
type = 'r';
}
}
if(type == 'l')
prev->left = get_new_node(val);
else
prev->right = get_new_node(val);
return root;
}
int find_minimum_value(bst_t *ptr)
{
int min = ptr ? ptr->data : 0;
while(ptr) {
if(ptr->data < min) min = ptr->data;
if(ptr->left) {
ptr = ptr->left;
} else if(ptr->right) {
ptr = ptr->right;
} else ptr = NULL;
}
return min;
}
bst_t *delete(bst_t *root, int val)
{
bst_t *prev = NULL, *ptr = root;
char type = ' ';
while(ptr) {
if(ptr->data == val) {
if(!ptr->left && !ptr->right) { // node to be removed has no children's
if(ptr != root && prev) { // delete leaf node
if(type == 'l')
prev->left = NULL;
else
prev->right = NULL;
} else root = NULL; // deleted node is root
} else if (ptr->left && ptr->right) { // node to be removed has two children's
ptr->data = find_minimum_value(ptr->right); // find minimum value from right subtree
val = ptr->data;
prev = ptr;
ptr = ptr->right; // continue from right subtree delete min node
type = 'r';
continue;
} else { // node to be removed has one children
if(ptr == root) { // root with one child
root = root->left ? root->left : root->right;
} else { // subtree with one child
if(type == 'l')
prev->left = ptr->left ? ptr->left : ptr->right;
else
prev->right = ptr->left ? ptr->left : ptr->right;
}
}
free(ptr);
}
prev = ptr;
if(val < ptr->data) {
ptr = ptr->left;
type = 'l';
} else {
ptr = ptr->right;
type = 'r';
}
}
return root;
}
Nice post. Just a suggestion. I believe, finding a minimum value in a BST doesn't have to traverse the right subtree. Minimum value must be either on the left subtree or node itself(in case if left subtree is null). Function find_minimum_value can be optimized if right subtree traversal is removed.
int find_minimum_value(bst_t *ptr)
{
while(ptr->left) {
ptr = ptr->left;
}
return ptr->data;
}
In C, you can cast the pointers in the tree to intptr_t type and perform bitwise operations to them.
As you traverse down the tree, you can store the 'parent' pointer of a node by xoring it with the pointer you traversed with. You can then traverse back up the tree by xoring the the address of the node you are coming from with the modified pointer.
A worked example of this traditional technique is at http://sites.google.com/site/debforit/efficient-binary-tree-traversal-with-two-pointers
Given the ability to traverse the tree without recursion, you can then create iterative versions of any of the algorithms based on traversing the tree.

Resources