Deleting Node in Binary Search Tree - c++

I have written code to delete a node in Binary Search Tree.
Code :
#include<iostream>
using namespace std;
struct Node {
int value;
Node* left;
Node* right;
};
Node* GetNewNode(int data) {
Node* newNode = new Node();
newNode->value = data;
newNode->left = newNode->right = NULL;
return newNode;
}
void Insert(Node* &root,int x)
{
if(root==NULL) root=GetNewNode(x);
else if(x>root->value) Insert(root->right,x);
else Insert(root->left,x);
}
Node* Search(Node* root,int x)
{
if(root->value==x) return root ;
else if(root->value>x) Search(root->left,x);
else if(root->value<x) Search(root->right,x);
}
Node* Searchmin(Node* root)
{
if(root==NULL) cout<<"Empty tree"<<endl;
if(root->left==NULL) return root;
else Searchmin(root->left);
}
void Inorder(Node* root)
{
if(root==NULL) return;
else {
Inorder(root->left);
cout<<root->value<<endl;
Inorder(root->right);
}
}
Node* deleteNode(Node* root, int x)
{
Node* nodeptr;
nodeptr=Search(root,x);
if(nodeptr->left==NULL && nodeptr->right==NULL) return nodeptr;
else if(nodeptr->left==NULL && nodeptr->right!=NULL)
{
nodeptr->value=nodeptr->right->value;
nodeptr=nodeptr->right;
return nodeptr;
}
else if(nodeptr->right==NULL && nodeptr->left!=NULL)
{
nodeptr->value=nodeptr->left->value;
nodeptr=nodeptr->left;
return nodeptr;
}
else{
nodeptr->value=Searchmin(nodeptr->right)->value;
deleteNode(nodeptr->right,nodeptr->value);
return nodeptr;}
}
int main()
{
Node* root=NULL;
Insert(root,20);
Insert(root,15);
Insert(root,25);
Insert(root,10);
Insert(root,16);
Insert(root,7);
Inorder(root);
Node* x=deleteNode(root,7);
delete x;
Inorder(root);
}
Compiler doesn't show any syntax error either. The program is crashing. Its not even deleting leaf node. I can't find the error. Please help.
(These lines are just to extend length of question because stackoverflow was not accepting generating error in question on lines of long code and short description.)

The first thing your delete function does is call search, and what's the first thing search does?
Node* Search(Node* root,int x)
{
if(root->value==x) return root ;
Search immediately dereferences root. It never checks for a null pointer. This means it's guaranteed your search function will dereference a null pointer if there is no node in the tree to be found.

Related

Inserting elements in a bst using recursion

I'm trying to add elements enter by the user in a BST.For this I've used 2 functions, one is used to create the function and other is just used to insert element to the tree. One is a pre-order function that is used to check if insertion is done or not Initially I tried to add elements manually.Its not printing all inserted values.
The overall layout
struct Node{
int data;
struct Node* left;
struct Node* right;
};
void Inorder(struct Node* root){
if(root==NULL){
return;
}
else{
Inorder(root->left);
cout<<root->data<<" ";
Inorder(root->right);
}
}
struct Node* create_node(int data){
struct Node* node=(struct Node*) malloc(sizeof(struct Node));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
The problem code:-
struct Node* insert(struct Node* root,int data){
static struct Node* prev=NULL;
if(root==NULL && prev==NULL){
return create_node(data);
}
if(root->data==data){
return root;
}
else{
if(root==NULL){
struct Node* ptr=create_node(data);
if(prev->data>data){
prev->left=ptr;
return root;
}
else{
prev->right=ptr;
return root;
}
}
else{
if(root->data>data){
prev=root;
insert(root->left,data);
}
else{
prev=root;
insert(root->right,data);
}
}
}
}
MAIN
int main()
{
struct Node* root=NULL;
root=insert(root,5);
Inorder(root);
cout<<endl;
insert(root,3);
Inorder(root);
insert(root,10);
Inorder(root);
return 0;
}
One thing I noticed that prev is static once we call insert for inserting next element(here 3) it won't roll over from start again because it is declared static.To overcome that
Tried to optimize the problem code by making prev as global and making null in main every time I call insert function in the main(), The optimised code is as follows:
#include <iostream>
#include<stdlib.h>
using namespace std;
static struct Node* prev=NULL;
struct Node{
int data;
struct Node* left;
struct Node* right;
};
void Inorder(struct Node* root){
if(root==NULL){
return;
}
else{
Inorder(root->left);
cout<<root->data<<" ";
Inorder(root->right);
}
}
struct Node* create_node(int data){
struct Node* node=(struct Node*) malloc(sizeof(struct Node));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
struct Node* insert(struct Node* root,int data){
if(root==NULL && ::prev==NULL){
return create_node(data);
}
if(root->data==data){
return root;
}
else{
if(root==NULL){
struct Node* ptr=create_node(data);
if(::prev->data>data){
::prev->left=ptr;
return root;
}
else{
::prev->right=ptr;
return root;
}
}
else{
if(root->data>data){
::prev=root;
insert(root->left,data);
}
else{
::prev=root;
insert(root->right,data);
}
}
}
}
int main()
{
struct Node* root=NULL;
root=insert(root,5);
Inorder(root);
cout<<endl;
::prev=NULL;
insert(root,3);
Inorder(root);
::prev=NULL;
insert(root,10);
Inorder(root);
return 0;
}
This is not how insertion into a BST is supposed to work. You don't need a prev pointer at all.
One of the issues in your code is that you don't use the return value of the recursive call, which at some point is going to be the pointer to a new node! You should really assign that return value to either the left or right member of the current node.
Also, the following if condition will never be true, as at that point it was already guaranteed that root is not NULL:
else{
if(root==NULL){
The correct code is actually quite simple:
struct Node* insert(struct Node* root, int data){
if (root == NULL) {
root = create_node(data);
} else if (root->data > data) {
root->left = insert(root->left, data);
} else if (root->data < data) {
root->right = insert(root->right, data);
}
return root;
}
I would also add some line breaks to the output in your main code:
int main()
{
struct Node* root = NULL;
root = insert(root, 5);
Inorder(root);
cout << endl;
insert(root, 3);
Inorder(root);
cout << endl;
insert(root, 10);
Inorder(root);
cout << endl;
return 0;
}
The issue that I noticed in my code (Unfortunately unable to upload the snippet). was in the part mentioned below.
if(root->data==data){
return root;
}
Firstly let me explain the recursion function, at beginning the root would be null at insertion(here inserting 5 as root) so first condition will be satisfied i.e.
if(root==NULL && ::prev==NULL){
return create_node(data);
}
and the function would return,now I set the global variable prev as NULL because I want to traverse again from the root of the tree to add the next element.
Now once we try to add another element (here adding element 3). This condition
if(root==NULL && ::prev==NULL){
return create_node(data);
}
won't be true, now the thought process while writing the logic was checking if at some stage while traversing down the tree if we encounter node with same value then we'll return the root and terminate the function. This is what I tried to implement .
Here's the code if you could relate(Problem Code Snippet)
else if(root->data==data){
return root;
}
No doubt approach is fine but I forgot to add one condition(actually I preempted that at this stage the root won't be NULL) but root can be NULL.
Because of this we will face segmentation fault error (in debugger mode -> which helped me to find the error in my code!).
So the correct code would be:
else if(root && root->data==data){// or if(root!=NULL && root->data=data)
return root;
}
Rest of the code remains unaltered
So to sum up when traversing through tree we return true for all conditions and once we reach NULL then since first condition won't we satisfied as prev!=NULL, so it comes to next condition root->data==data but here root=NULL so we get
segmentation fault error and function never encounters ROOT==NULL which was designed for this purpose only i.e. to add/insert element in the tree as everything seems fine on traversing the tree. So to over come this problem I modified my else if condition i.e. else if(root && root->data==data)
so the full function code is as follows:
struct Node* insert(struct Node* root,int data){
if(root==NULL && ::prev==NULL){
return create_node(data);
}
else if(root && root->data==data){
return root;
}
else{
if(root==NULL){
struct Node* ptr=create_node(data);
if(::prev->data>data){
::prev->left=ptr;
return root;
}
else{
::prev->right=ptr;
return root;
}
}
else{
if(root->data>data){
::prev=root;
insert(root->left,data);
}
else{
::prev=root;
insert(root->right,data);
}
}
}
}
PS: The code was executed for many trees including one mentioned in the question and got the expected results i.e. Inorder was a sorted array which depicts that insertion was done correctly.

can u use head->data as an integer variable, if the "data" is integer type in chained lists?

can u use head->data as an integer variable, if the "data" is integer type in chained lists.
for example, I have a code where I have to transform a simply chained list of integer variables, into 2 lists, one with positive numbers, the other one with negative numbers. I cant find the error in my code...
using namespace std;
struct Node{
int data;
Node* next;
};
Node* head=new Node;
Node* pozitiv=NULL;
Node* negativ=NULL;
Node* newNode(int data)
{
Node* nodNou = new Node();
nodNou -> data = data;
nodNou -> next = NULL;
return nodNou;
}
void Push(Node* &top, int data)
{
Node* nodNou = newNode(data);
nodNou -> next = top;
top = nodNou;
}
void read(){
Node* aux=new Node;
int r,i,v[1000];
cout<<"insert the number of elements in list"<<endl;
cin>>r;
cin>>v[0];
head->data=v[0];
head->next=NULL;
for(i=1;i<r;i++){
cin>>v[i];
aux->data=v[i];
aux->next=head;
head=aux;
aux=new Node;
}
}
write(){
if(head==NULL) return 0;
else{
while(head!=NULL){
cout<<head->data<<"->";
head=head->next;
}
}
cout<<endl<<endl;
}
void stivezlutat(){
Node* aux;
pozitiv=new Node;
pozitiv->next=NULL;
negativ=new Node;
negativ->next=NULL;
while(head!=NULL){
if(head->data >= 0){
Push(pozitiv, head->data);
}
else{
Push(negativ, head->data);
}
head=head->next;
}
cout<<"pozitive list:"<<endl;
while(pozitiv != NULL){
cout<<pozitiv->data<<"->";
pozitiv=pozitiv->next;
}
cout<<endl;
cout<<"negative list:"<<endl;
while(negativ != NULL){
cout<<negativ->data<<"->";
negativ=negativ->next;
}
}
int main()
{
read();
write();
stivezlutat();
}```
Errors in your code:
Required #include directives don't present.
extra "```" exists at the end of code.
No return type is specified for write.
In the function write, return with value is used while no return statement presents at the end of the function, so no return type is valid for that.
The function write breaks the value of head, so the function stivezlutat will see empty list.
Extra nodes are assigned to pozitiv and negativ and they are printed in the funciton stivezlutat.
Fixed code (also indentation is fixed):
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
Node* head=new Node;
Node* pozitiv=NULL;
Node* negativ=NULL;
Node* newNode(int data)
{
Node* nodNou = new Node();
nodNou -> data = data;
nodNou -> next = NULL;
return nodNou;
}
void Push(Node* &top, int data)
{
Node* nodNou = newNode(data);
nodNou -> next = top;
top = nodNou;
}
void read(){
Node* aux=new Node;
int r,i,v[1000];
cout<<"insert the number of elements in list"<<endl;
cin>>r;
cin>>v[0];
head->data=v[0];
head->next=NULL;
for(i=1;i<r;i++){
cin>>v[i];
aux->data=v[i];
aux->next=head;
head=aux;
aux=new Node;
}
}
void write(){
if(head==NULL) return;
else{
Node* cursor = head;
while(cursor!=NULL){
cout<<cursor->data<<"->";
cursor=cursor->next;
}
}
cout<<endl<<endl;
}
void stivezlutat(){
Node* aux;
pozitiv=NULL;
negativ=NULL;
while(head!=NULL){
if(head->data >= 0){
Push(pozitiv, head->data);
}
else{
Push(negativ, head->data);
}
head=head->next;
}
cout<<"pozitive list:"<<endl;
while(pozitiv != NULL){
cout<<pozitiv->data<<"->";
pozitiv=pozitiv->next;
}
cout<<endl;
cout<<"negative list:"<<endl;
while(negativ != NULL){
cout<<negativ->data<<"->";
negativ=negativ->next;
}
}
int main()
{
read();
write();
stivezlutat();
}

incorrect output of binary search tree

I've already debugged the code and did not find any mistake. Below code does not print all the data of binary search tree(BST).Only root node and last two node get display in inorder traversal.
struct node{
int key;
node *left;
node *right;
};
node* newNode(int data){
node *ptr=new node;
ptr->key=data;
ptr->left=ptr->right=NULL;
return ptr;
}
node* insert_node(node* root,int data){
if(root==NULL){
root=newNode(data);
}else if(data<=root->key){
root->left=newNode(data);
}else{
root->right=newNode(data);
}
return root;
}
void inorder(node* root){
if(root==NULL)
return;
inorder(root->left);
cout<<root->key<<" ";
inorder(root->right);
}
int main(){
node *root=NULL;
root=insert_node(root,10);
root=insert_node(root,12);
root=insert_node(root,15);
root=insert_node(root,1);
root=insert_node(root,20);
inorder(root);
return 0;
}
The insert function is not having any recursive or iterative implementation that will find the leaf node. So the new node will replace the child nodes of root node. And I think that is very well highlighted in comment section.
Here's a block of code in which the leaf node is located by use of iteration and then the new node is inserted.
node *insert_node( node *root, int data){
struct node *ptr, *nodeptr, *parentptr;
ptr = (struct node*)malloc(sizeof(struct node));
ptr->data = data;
ptr->left = NULL;
ptr->right = NULL;
if(root==NULL) //tree is empty
{
root=ptr;
root->left=NULL;
root->right=NULL;
}
else
{
parentptr=NULL; // keep the address of parent node
nodeptr=root;
while(nodeptr!=NULL)
{
parentptr=nodeptr;
if(data<nodeptr->data)
nodeptr=nodeptr->left;
else
nodeptr = nodeptr->right;
}
// now the parentptr contains address of the leaf node
if(data<parentptr->data)
parentptr->left = ptr;
else
parentptr->right = ptr;
}
return root;
}
You can also refer to some other sources for recursive implementation of the same.

Why can't I insert nodes after head into a C++ linked list?

Could someone please help me identify the problem with the code below.
#include <iostream>
using namespace std;
struct node
{
int a,b;
struct node* next=NULL;
};
node* head=NULL;
void insert(int a,int b)
{
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
return;
}
node* cur=head;
while(cur!=NULL)
{
cur=cur->next;
}
cur=new node;
cur->a=a;
cur->b=b;
return;
}
void display()
{
node* cur=head;
while(cur!=NULL)
{
cout<<cur->a<<"\t"<<cur->b<<"\n";
cur=cur->next;
}
}
int main()
{
int i;
for(i=0;i<3;++i)
{
insert(i,i+1);
}
display();
//cout<<h->next->a;
return 0;
}
This is the output that I get:
0 1
It seems that I can only display the head node and none after gets inserted. If I try to access the next node after head, I get a segmentation fault. Why is that?
Your search code is:
node* cur=head;
while(cur!=NULL)
{
cur=cur->next;
}
cur=new node;
At the end of the loop, you've found the right place to add the new node, but you overwrite that with cur = new node; — so you need to use something more like:
node *new_node = new node;
new_node->a = a;
new_node->b = b;
new_node->next = nullptr;
cur->next = new_node;
Or, equivalently:
cur->next = new node;
cur->next->a = a;
cur->next->b = b;
cur->next->next = nullptr;
Even better, you'd create a constructor for the struct node class, such as:
node(int a_init = 0, int b_init = 0) : a(a_init), b(b_init), next(nullptr) { }
and then:
cur->next = new node(a, b);
would do the whole initialization job.
While inserting, update head->next to NULL (when head is NULL)
and curr->next to NULL (when some elements are already in the list)
respectively.
You are not linking head to curr. To link head and curr, you can
create another pointer instead to hold the new element, say new_ptr.
Keep curr such that curr->next=NULL, and then write
curr->next=new_ptr.
void insert(int a,int b)
{
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
head->next=NULL;
return;
}
node* cur=head,*new_ptr;
while(cur->next!=NULL)
{
cur=cur->next;
}
new_ptr=new node;
new_ptr->a=a;
new_ptr->b=b;
new_ptr->next=NULL;
curr->next=new_ptr;
return;
}
I found out the bug .While inserting , instead of sitting in a node and checking if it is null , look 1 node ahead and check if its null. Because if you don't , then the list will get broken and cpp allocates memory else where rather than to the pointer of the last list node's next branch.
Modified insert function :
void insert(int a,int b)
{
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
head->next=NULL;
return;
}
node* cur=head;
while(cur->next!=NULL)
{
//cout<<cur->a<<"\t"<<cur->b<<"\n";;
cur=cur->next;
}
cur->next=new node;
cur->next->a=a;
cur->next->b=b;
return;
}
At the time of creation of any node , the next pointer of that node becomes null as per the definition of your node.
struct node
{
int a,b;
struct node* next=NULL;
};
Now,after the creation of start node ,the next pointer of start node is NULL.And when u created your second node ,you didn't point the next node of your first node to the second node.Then how will you be able to reach to the second node if you do not have the pointer to the second node.
So the solution will be --
void insert(int a,int b)
{
node *temp;
if(head==NULL)
{
head=new node;
head->a=a;
head->b=b;
temp=head;
return;
}
node* cur=head;
while(cur!=NULL)
{
cur=cur->next;
}
cur=new node;
temp->next=cur;
cur->a=a;
cur->b=b;
temp=cur;
return;
}

Recursive insertion of BST

I have made a function for insertion in BST using loops and it is working perfectly fine.
Now, when iam writing to do it using recursion i don't know why it's not working properly, however the logic is correct according to me. It seems that no newnode is being added to the BST tree and head of the tree after coming out of the insertion function is again becoming NULL.
#include <iostream>
using namespace std;
class node{
public:
int data;
node *right;
node *left;
node(){
data=0;
right=NULL;
left=NULL;
}
};
class tree{
node *head;
int maxheight;
void delete_tree(node *root);
public:
tree(){head=0;maxheight=-1;}
void pre_display(node* root);
node* get_head(){return head;}
void insert(int key,node* current);
};
void tree::insert(int key,node *current){
if(current==NULL)
{
node *newnode=new node;
newnode->data=key;
current=newnode;
}
else{
if(key<current->data)
insert(key,current->left);
else
insert(key,current->right);
}
return;
}
void tree::pre_display(node *root){
if(root!=NULL)
{
cout<<root->data<<" ";
pre_display(root->left);
pre_display(root->right);
}
}
int main(){
tree BST;
int arr[9]={17,9,23,5,11,21,27,20,22},i=0;
for(i=0;i<9;i++)
BST.insert(arr[i],BST.get_head());
BST.pre_display(BST.get_head());
cout<<endl;
system("pause");
return 0;
}
Please tell me what should i change in the algorithm to make it work.
In your insert function
void tree::insert(int key,node *current){
if(current==NULL)
{
node *newnode=new node;
newnode->data=key;
current=newnode;
}
else{
if(key<current->data)
insert(key,current->left);
else
insert(key,current->right);
}
return;
}
you allocate a new node but never set BST::head to newly allocated head. So BST::get_head will always return null.
One way to fix this would be for insert to return a node. This would be root node in your case and set the BST::head to this value.
Your recursion looks fine, but you don't actually add the node anywhere! You just recurse through the tree.
Edit You can change the insert method to take a pointer to a pointer, like this:
void tree::insert(int key, node **current)
{
if(*current == NULL)
{
node *newnode = new node;
newnode->data = key;
*current = newnode;
}
else
{
if(key < (*current)->data)
insert(key, &(*current)->left);
else
insert(key, &(*current)->right);
}
}
And in main call it like this:
BST.insert(arr[i], &BST.get_head()); // Note the ampersand (&)
you should try this
node tree:: insert ( int key , node * current ) {
if ( ! current ) {
node * newnode = new node ;
newnode -> key = key;
current = newnode ;
}
else if ( key < current -> key ) {
current -> left = insert ( key , current ->left
}
else
current -> right = insert ( key , current->right )
return current ;
}
it works fine....jsut update the head node every time whenver a new node is inserted and it will return the updated current node.
Just change your function as
void tree::insert(int key,node*& current){
if(current==NULL)
{
node *newnode=new node;
newnode->data=key;
current=newnode;
}
else{
if(key<current->data)
insert(key,current->left);
else
insert(key,current->right);
}
return;
}
make your input pointer as a reference parameter.
struct node{
node* left;
node* right;
int data;
};
node* root=NULL;
node* create(node* head,int val){
if(head==NULL){
node* nn=new node;
nn->data=val;
nn->left=NULL;
nn->right=NULL;
head=nn;
}
else if(val<head->data)
head->left=create(head->left,val);
else if(val>head->data)
head->right=create(head->right,val);
return head;
}
int main(){
int num=0;
cout<<"Enter value in tree or press -1 to Exit\n";
while(num!=-1){
cin>>num;
if(num==-1){
cout<<"\nTree Created\n";
break;
}
else{
root=create(root,num);
}
}
}
hope this code solves your problem
void insertNode_recursive(int value, TreeNode *current)
{
if (current == NULL)
{
if (current == NULL && isEmpty())
{
TreeNode *new_node = new TreeNode(value);
current = new_node;
root = new_node;
}
else
{
TreeNode *new_node = new TreeNode(value);
current = new_node;
}
}
else
{
if (value < current->getValue())
{
insertNode_recursive(value, current->getLeft());
}
else if (value > current->getValue())
{
insertNode_recursive(value, current->getRight());
}
else
{
cout << "\nDuplicate Value are Not Allowed\n";
}
}
}
This Code is Useful For Recursively Print the Tree Node