What is wrong with this function to delete node from a BST? - c

I simply want to delete a node from the BST and this gives me an error that new is undefined.
The ADT is like this:
typedef struct BSTNode *BSTree;
struct BSTNode {
int value;
BSTree left;
BSTree right;
};
BSTree Delete(BSTree t, int item) {
if (item < t->value) {
t->left = Delete(t->left, item);
} else if (item > t->value) {
t->right = Delete(t->right, item);
} else {
// deleting item
if (t->left == NULL && t->right == NULL) {
BSTree new = NULL;
} else if (t->left == NULL) {
BSTree new = t->right;
} else if (t->right == NULL) {
BSTree new = t->left;
// } else {
//BSTree new = joinTrees(t->left, t->right);
}
free(t);
t = new;
}

The problem is that you are declaring multiple variables that only exist within each containing conditional block. Declare the variable at the top of the function or top of the else block. Then set that same variable in each conditional block of code.
BSTree Delete(BSTree t, int item) {
BSTree new_item;
if (item < t->value) {
t->left = Delete(t->left, item);
} else if (item > t->value) {
t->right = Delete(t->right, item);
} else {
// deleting item
if (t->left == NULL && t->right == NULL) {
new_item = NULL;
} else if (t->left == NULL) {
new_item = t->right;
} else if (t->right == NULL) {
new_item = t->left;
// } else {
//BSTree new = joinTrees(t->left, t->right);
}
free(t);
t = new_item;
}

Related

doubly linked list problem with removal and push back maybe

In the main function, I tried to push front couple numbers and push back couple numbers and then remove pos = 0 and pso = 1. However, in the output, remove at pos = 0 and remove at pos = 1 prints out number 5 and number 7 which are wrong. It should be 4 and 2. I cannot find which part I am wrong. Here is my code:
#ifndef MYDLL_H
#define MYDLL_H
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
struct node *previous;
} node_t;
typedef struct DLL
{
int count;
node_t *head;
node_t *tail;
} dll_t;
dll_t *create_dll()
{
dll_t *myDLL = (dll_t*)malloc(sizeof(dll_t));
if (myDLL == NULL) {
return NULL;
}
myDLL->count = 0;
myDLL->head = NULL;
myDLL->tail = NULL;
return myDLL;
}
int dll_empty(dll_t *l)
{
if (l == NULL) {
return -1;
}
if (l->count == 0 && l->head == NULL) {
return 1;
} else {
return 0;
}
}
int dll_push_front(dll_t *l, int item)
{
if (l == NULL) {
return -1;
}
node_t* new = (node_t*)malloc(sizeof(node_t));
if (new == NULL) {
return -1;
}
new->data = item;
new->next = l->head;
new->previous = NULL;
if (l->head != NULL) { //set new prev for the previous head before pushing.
l->head->previous = new;
}
l->head = new; // reset the new head for l.
l->count++;
return 1;
}
int dll_push_back(dll_t *l, int item)
{
if (l == NULL) {
return -1;
}
node_t* new = (node_t*)malloc(sizeof(node_t));
if (new == NULL) {
return -1;
}
new->data = item;
new->previous = l->tail;
new->next = NULL;
if(l->tail != NULL) {
l->tail->next = new;
} else {
l->head = new;
}
l->tail = new;
l->count++;
return 1;
}
int dll_pop_front(dll_t *t)
{
if (t == NULL || t->head == NULL) {
return -1;
}
node_t* pop_pointer = t->head;
int pop_item = pop_pointer->data;
t->head = pop_pointer->next; // set new head.
if (t->head != NULL) {
t->head->previous = NULL;
} else { // t->head = NULL cuz only one item and after popping, the t->head is null.
t->tail = NULL; // else if t->head = NULL, then t->tail also should be NULL.
}
if (t->head == NULL) {
t->tail = NULL;
}
t->count--;
free(pop_pointer);
return pop_item;
}
int dll_pop_back(dll_t *t)
{
if (t == NULL || t->head == NULL) {
return -1;
}
node_t* pop_pointer = t->tail;
int pop_item = pop_pointer->data;
t->tail = pop_pointer->previous;
if (t->tail != NULL) {
t->tail->next = NULL;
} else {
t->head = NULL;
}
if (t->head == NULL) {
t->tail = NULL;
}
t->count--;
free(pop_pointer);
return pop_item;
}
int dll_insert(dll_t *l, int pos, int item)
{
if (l == NULL) {
return -1;
}
if (pos >= l->count || pos < 0) {
return 0;
}
node_t* new = (node_t*)malloc(sizeof(node_t));
if (new == NULL) {
return 0;
}
new->data = item;
if(pos == 0) {
return dll_push_front(l, item);
}
node_t* pointer = l->head;
for (int i = 0; i < pos - 1; i++) {
pointer = pointer->next;
}
//ex: pos = 1, no for loop, pointer still head.
new->previous = pointer;
new->next = pointer->next;
pointer->next->previous = new;
pointer->next = new;
l->count++;
return 1;
}
int dll_get(dll_t *l, int pos)
{
if (l == NULL) {
return -1;
}
if (pos < 0 || pos >= l->count) {
return 0;
}
node_t* pointer = l->head;
for (int i = 0; i < pos - 1; i++) {
pointer = pointer->next;
}
return pointer->data;
}
int dll_remove(dll_t *l, int pos)
{
if (l == NULL) {
return -1;
}
if (pos < 0 || pos >= l->count) {
return 0;
}
node_t* pointer = l->head;
node_t* prev = NULL; // first node prev is null.
for (int i = 0; i < pos; i++) {
prev = pointer;
pointer = pointer->next;
}
if (prev == NULL) { // first item.
l->head = pointer->next;
} else {
prev->next = pointer->next;
}
if (pointer->next != NULL) {
pointer->next->previous = prev;
}
// if we are removing the tail node
if (pointer == l->tail) {
l->tail = prev;
}
int removed_value = pointer->data;
free(pointer);
l->count--;
return removed_value;
}
int dll_size(dll_t *t) {
if (t == NULL) {
return -1;
}
return t->count;
}
void free_dll(dll_t *t)
{
if (t == NULL) {
return;
}
if (t == NULL) {
free(t);
return;
}
node_t* pointer = t->head;
while(pointer != NULL) {
node_t* pointer2 = pointer;
pointer = pointer->next;
free(pointer2);
}
free(t);
}
#endif

How can I delete a node from Binary search tree in C with 2 children

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 .there is an issue while deleting elements.why?

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

Binary search tree delete not working, why?

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

Iteratively inserting into a binary tree

I came across some threads on StackOverflow but none of them quite cleared my doubts.
So the problem is simple. I need to iteratively insert elements into a binary tree. And this is my code.
BST newNode(int x)
{
BSTNodePtr node = (BSTNodePtr) malloc(sizeof(struct TreeNode));
node->Element = x;
node->Left = NULL;
node->Right = NULL;
return node;
}
BST Insert(int x, BST T)
{
BST temp_node = T;
while( T != NULL) {
if (x < T->Element)
T = T->Left;
else if (x >= T->Element)
T = T->Right;
}
T = newNode(x);
return temp_node;
}
However, when I'm finding the height of this tree I am always getting 0. The height code is
int Height(BST T)
{
if (T == NULL)
return 0;
return 1+(max(Height(T->Left), Height(T->Right)));
}
and this works perfectly fine when I do insertion recursively (using a function with the exact same signature)
What am I missing?
Here:
BST Insert(int x, BST T)
{
BST temp_node = T;
while( T != NULL) {
if (x < T->Element)
T = T->Left;
else if (x >= T->Element)
T = T->Right;
}
T = newNode(x);
return temp_node;
}
You navigate the tree until you hit T == NULL. Then you create a node and assign the pointer to it to T. Then you return the original value of T. You don't modify your tree at all. No node in it is made to point to the newly created node. T is just a local variable.
Couldn't solve the problem that way. This code, however, seems to work.
BST Insert(int x, BST T)
{
BST temp=T;
BST node=(BST)malloc(sizeof(struct TreeNode));
node->Element=x;
node->Left=NULL;
node->Right=NULL;
if (T==NULL)
{
T=node;
return(T);
//printf("%d\n",T->Element);
}
else
{
while(1)
{
if (temp->Element>=node->Element && temp->Left==NULL)
{
temp->Left=node;
break;
}
else if (temp->Element>=node->Element && temp->Left!=NULL)
{
temp=temp->Left;
}
else if (temp->Element<node->Element && temp->Right==NULL)
{
temp->Right=node;
break;
}
else
{
temp=temp->Right;
}
}
return(T);
}
}
Here's My implementation of the aforementioned problem:
bst* newNode(int x)
{
bst* T = new bst;
T->value = x;
T->left_child = T->right_child = NULL;
return T;
}
bst* bst_insert_iter(bst* T,int val)
{
if (T == NULL)
T = newNode(val);
else
{
bst *temp_node = T;
bool flag = true;
while(flag)
{
if (val <= temp_node->value)
{
if (temp_node->left_child == NULL)
{
temp_node->left_child=newNode(val);
flag = false;
}
else
temp_node = temp_node->left_child;
}
else
{
if (temp_node->right_child == NULL)
{
temp_node->right_child=newNode(val);
flag = false;
}
else
temp_node = temp_node->right_child;
}
}
}
return T;
}
You have the bug in your insert function. As I may assume, initially your tree is empty. so the first time you insert a node, the second argument is NULL, right? Then this function always returns NULL to you as you always pass a NULL value.
template <class T>
class TreeNode{
private:
T data;
TreeNode<T>* right,*left;
public:
void setData(T d){
this->data =d;
}
T getData(){
return this->data;
}
void setRight(TreeNode<T>* r){
this->right =r;
}
TreeNode<T>* getRight(){
return this->right;
}
void setLeft(TreeNode<T>* r){
this->left =r;
}
TreeNode<T>* getLeft(){
return this->left;
}
static TreeNode<T>* newNode(T data){
TreeNode<T>* n = new TreeNode<T>();
n->setData(data);
n->setRight(NULL);
n->setLeft(NULL);
return n;
}
};
template <class T>
class BinaryTree{
private:
TreeNode<T>* root;
public:
void insert(T data){
TreeNode<T>* n = TreeNode<T>::newNode(data);
if(root==NULL)
root = n;
else{
TreeNode<T>* t = root;
while(t!=NULL){
if(n->getData() >= t->getData()){
if(t->getRight()==NULL){
t->setRight(n); //newnode attached as right child in tree
t = NULL;
}
else
t = t->getRight();
}
else{
if(t->getLeft()==NULL){
t->setLeft(n); //newnode attached as left child in tree
t=NULL;
}
else
t = t->getLeft();
}
}
}
}
void preorder(){
TreeNode<T>* t = root;
preorderUtil(t);
}
void preorderUtil(TreeNode<T>* node){
if(node==NULL)
return;
preorderUtil(node->getLeft());
cout<<node->getData()<<" ";
preorderUtil(node->getRight());
}
};
Your changes are not reflected in the tree. I followed this way to insert data iteratively and it works fine. The point is making a node inside your binarytree to point the newly created node such that it gets attached to the tree.
Here is my version , it seems to be working.
struct tree{
tree *left;
tree *right;
int key;
};
void insertBst(int k,tree *t)
{
tree *newK = new tree[sizeof(tree)];
newK->key = k;
newK->left = NULL;
newK->right = NULL;
if((t)->key == NULL)
{
t=newK;
return;
}
else{
bool found = false;
tree *root = t;
tree *parent = NULL;
while(root != NULL)
{
parent = root;
if(root->key < newK->key)
{
root=root->right;
}
else if(root->key > newK->key)
{
root=root->left;
}
else{
//Here we have duplicates!! so do nothing
root = root;
}
}
if(parent->key > newK->key) parent->left = newK;
else parent->right = newK;
}
}

Resources