I am trying to implement Binary search tree in C.
But I am stuck at the delete operation, when I run the code it doesn't delete the value specified.
Before calling delete:(calling inorder())
16 19 23
After calling delete:(calling inorder())
16 19 23
code:
void deleteNode(struct node *n, int data)
{
struct node *temp;
if(n->data==data)
{
if(n->left == NULL && n->right == NULL)
{
n=NULL;
}
else if(n->left == NULL && n->right!=NULL)
{
n->data = (n->right)->data;
n->right = NULL;
}
else if(n->left!=NULL && n->right == NULL)
{
n->data = (n->left)->data;
n->left=NULL;
}
else if(n->left != NULL && n->right != NULL)
{
temp = findMax(root);
n->data = temp->data;
temp = NULL;
}
}
else if(n->data > data)
{
deleteNode(n->left, data);
}
else if(n->data < data)
{
deleteNode(n->right, data);
}
}
I have other code which is working, but I want to know what is wrong with this code?
Edit:
I have edited the code with a few changes in it.
Now, When I try to delete the ROOT node.
I end up with this:
(inorder traversal)-> 16 23 23
Now,
Why is this happening when temp = NULL is making the maximum node NULL.
Note: I am not initializing temp as the code has been changed and it is initialized just before its use (temp = findMax(root)).
code inorder():
void inorder(struct node *root)
{
if(root!=NULL)
{
inorder(root->left);
printf("%d\n", root->data);
inorder(root->right);
}
}
Use this alternative code or use your temp tree in your method
struct node *temp = n; //then use temp tree in code
Alternative method
struct node *delete(struct node *tree, int data)
{
if(find(tree,data)==-1 || tree == NULL)
return tree;
if(tree->data == data)
{
if(tree->left==NULL && tree->right==NULL)
return NULL;
if(tree->right != NULL){
tree->data = min(tree->right);
tree->right = delete(tree->right,min(tree->right));
return tree;
}
tree->data = madata(tree->left);
tree->left = delete(tree->left,madata(tree->left));
return tree;
}
if(tree->data < data)
{
tree->right= delete(tree->right,data);
return tree;
}
tree->left= delete(tree->left,data);
return tree;
}
This is what worked for me,
struct node* deleteNode(struct node *n, int data)
{
struct node *temp;
temp = n;
if(n->data==data)
{
if(n->left == NULL && n->right == NULL)
{
n=NULL;
return NULL;
}
else if(n->left == NULL && n->right!=NULL)
{
n = n->right;
temp = NULL;
}
else if(n->left!=NULL && n->right == NULL)
{
n = n->left;
temp = NULL;
}
else if(n->left != NULL && n->right != NULL)
{
temp = findMax(root);
n->data = temp->data;
temp = NULL;
}
}
else if(n->data > data)
{
n->left = deleteNode(n->left, data);
}
else if(n->data < data)
{
n->right = deleteNode(n->right, data);
}
return n;
}
Related
I am trying to create a function that deletes a node from a binary search tree my problem is whenever I delete a root node that has two children it will work but if I insert a node again there is an error in allocating memory(malloc) for the newly added node. I have tried using a debugger it will stuck in malloc and it doesn't tell me why.
Here is my function in deleting a node from the bst
bool delete_node(node * n, int data)
{
if(n == NULL)
return false;
if (n->data == data)
{
if(n->left == NULL && n->right == NULL)
{
free(n);
n->empty = true;
return true;
}
else if(n->left != NULL && n->right == NULL)
{
node * temp = n;
n = n->left;
free(temp);
temp->empty = true;
return true;
}
else if(n->left == NULL && n->right != NULL)
{
node * temp = n;
n = n->right;
free(temp);
temp->empty = true;
return true;
}
else
{
nodelist * inorder_seq = create_nodelist();
get_inorder_seq(inorder_seq, n);
node * ps = get_predecessor(inorder_seq, n);
if(ps == NULL)
ps = get_successor(inorder_seq, n);
int temp_data = n->data;
n->data = ps->data;
free(inorder_seq->list);
free(inorder_seq);
if(temp_data > n->data)
return delete_node(n->left, ps->data);
else
return delete_node(n->right, ps->data);
}
}
else if(n->data < data)
return delete_node(n->right, data);
else if(n->data > data)
return delete_node(n->left, data);
}
Here is my function in inserting a new node
void insert_node(node * root, int data)
{
node * newnode = create_node(data);
recur_insert_node(root, newnode);
}
Here is the function for the recursion of inserting a new node
void recur_insert_node(node * n, node * newnode)
{
if(n->data > newnode->data)
{
if(n->left == NULL || n->left->empty)
{
n->left = newnode;
n->left->empty = false;
}
else
{
recur_insert_node(n->left, newnode);
}
}
else if(n->data < newnode->data || n->right->empty)
{
if(n->right == NULL)
{
n->right = newnode;
n->right->empty = false;
}
else
{
recur_insert_node(n->right, newnode);
}
}
}
here is my node struct
typedef struct _node
{
int data;
struct _node * left;
struct _node * right;
bool empty;
}node;
it is a binary search tree with inorder traversal. there is an issue while printing elements. I can't solve the issue. The deletebst is not working. It still displays same. It could be a semantic error also. Maybe there is issue in inserting. Or some issue in displaying inorderly.
I am using a double pointer in the search function and calling it in delete function.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *llink;
struct node *rlink;
};
typedef struct node bstnode;
bstnode *root = NULL;
void
insert(int ele)
{
bstnode *cur,
*prev,
*temp;
temp = (bstnode *) malloc(sizeof(bstnode));
temp->data = ele;
temp->llink = temp->rlink = NULL;
cur = root;
prev = NULL;
if (root == NULL)
root = temp;
else {
while (cur != NULL) {
prev = cur;
if (ele < cur->data)
cur = cur->llink;
else
cur = cur->rlink;
}
if (ele < prev->data)
prev->llink = temp;
else
prev->rlink = temp;
}
}
void
inorder(bstnode * node)
{
if (node == NULL) {
return;
}
else if (node != NULL) {
inorder(node->llink);
printf("%d\n", node->data);
inorder(node->rlink);
}
}
bstnode *
search(int key, bstnode ** prev)
{
bstnode *cur;
(*prev) = NULL;
cur = root;
while (cur != NULL) {
if (key == cur->data)
return cur;
else {
(*prev) = cur;
if (key < cur->data)
cur = cur->llink;
else {
cur = cur->rlink;
}
}
}
return cur;
}
void
deletebst(int ele)
{
bstnode *cur,
*prev,
*insucc,
*inprev;
cur = search(ele, &prev);
if (cur->llink != NULL && cur->rlink != NULL) {
inprev = cur;
insucc = cur->rlink;
while (insucc->llink != NULL) {
inprev = insucc;
insucc = insucc->llink;
}
cur->data = insucc->data;
if (inprev == cur) {
inprev->rlink = insucc->rlink;
}
else
inprev->llink = insucc->rlink;
free(insucc);
return;
}
if (cur->llink != NULL && cur->rlink != NULL) {
if (cur == root) {
root = cur->rlink;
}
else if (prev->llink == cur)
prev->llink = cur->llink;
else {
prev->rlink = cur->llink;
}
cur = NULL;
free(cur);
return;
}
if (cur->llink == NULL && cur->rlink == NULL) {
if (cur == root)
root = NULL;
else if (prev->llink == cur)
prev->llink = NULL;
else {
prev->rlink = NULL;
}
return;
}
}
int
main()
{
insert(45);
insert(76);
insert(85);
deletebst(76);
inorder(root);
}
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.
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;
}
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.