double free or corruption when implement binary tree - c++

update:
add more code as asked.pasted to the end of question. Thanks everyone who stops.
current code is fine to delete a leaf, but come to Root, it can not delete.
====
update:
I revise the code, change removeRootMatch to
tmp = Root;
Root = tmp->Right;
tmp->Right = NULL;
delete tmp;
and no error but it does not delete the Node.
=====
The program is simple do the following step:
find min value of a binary tree;
record the min value in a vector;
delete the node with min value in the tree;
repeat 1-3 till the tree is empty.
I have removeNode()function, which will call removeRoot function(check code below),if the one needed to be removed is Root. But I have trouble with this function. I am doing some debug and found it is something wrong with removeRootMatch function. It give an error when run. the error I got is The error I got is *** glibc detected *** ./bintree: double free or corruption (fasttop): 0x0000000000727060 ***, any one can help me?
The tree is defined as following, language is c++
typedef struct myNode* LPNode;
typedef struct myNode Node;
struct myNode
{
double key;
LPNode Left; //left subtree
LPNode Right; //right subtree
};
Main part of program is as following:
nmax is initialed as 0,
sortedvector is alloacted a vector with space as large as the total nodes in the tree,
min is initialed as 99999.
minValue will return the min value of tree.
compareDouble(a,b) will return 1 if a < b,return 2 if a > b,return 3 if equal
code as following
void removeRootMatch(LPNode Root)
{
LPNode tmp = MakeNewNode(Root->key);
tmp->Left = Root->Left;
tmp->Right = Root->Right;
//no child
if(Root->Left==NULL && Root->Right == NULL) {
Root=NULL;
delete Root;
} else if(Root->Left==NULL && Root->Right!=NULL){ //one right child
//delete Root;
Root = tmp->Right;
tmp->Right = NULL;
delete tmp;
} else {
printf("Remove root bug!\n");
}
}
This is the function call removeNode function.
//compare double
int compareDouble(double a,double b)
{
if(a-b<-EPSILON) //a<b
return 1;
else if(a-b>EPSILON)//a>b
return 2;
else
return 3;
}
//find the min key in a tree
double minValue(LPNode Root,double min)
{
if(Root == NULL)
return min;
if(compareDouble(Root->key,min)==1)
min = Root->key;
min = minValue(Root->Left, min);
min = minValue(Root->Right, min);
return min;
}
//remove root
void removeRootMatch(LPNode& Root)
{
LPNode tmp = MakeNewNode(Root->key);
tmp->Left = Root->Left;
tmp->Right = Root->Right;
//no child
if(Root->Left==NULL && Root->Right == NULL) {
Root=NULL;
delete Root;
} else if(Root->Left==NULL && Root->Right!=NULL){ //one right child
double k = Root->key;
Root = tmp->Right;
tmp->Right = NULL;
delete tmp;
//tmp=tmp->Right;
//Root->Right = NULL;
//delete Root;
//Root = tmp;
} else {
printf("Remove root bug!\n");
}
}
//remove a node
void removeMatch(LPNode& Root,LPNode match,bool left)
{
//no child
if(match->Left==NULL && match->Right == NULL){
double k = match->key;
left==true?
Root->Left=NULL:
Root->Right=NULL;
delete match;
if(!Root->Left)printf("%f ",k);
}
else if(match->Left==NULL && match->Right!=NULL){//one right child
double k = match->key;
left==true?
Root->Left=match->Right:
Root->Right=match->Right;
delete match;
if(!Root->Left)printf("%f ",k);
} else {
printf("Remove root bug!\n");
}
}
//delete a node
void removeNode(LPNode Root,double min)
{
if(compareDouble(min,Root->key)==3){
removeRootMatch(Root);
}else if(compareDouble(min,Root->key)==1 && Root->Left != NULL) {
compareDouble(min,Root->Left->key)==3 ?
removeMatch(Root,Root->Left,true):
removeNode(Root->Left,min);
}else if(compareDouble(min,Root->key)==2 && Root->Right != NULL){
compareDouble(min,Root->Right->key)==3 ?
removeMatch(Root,Root->Right,false):
removeNode(Root->Right,min);
}else{
printf("Remove bug1!\n");
}
}
//call minValue to find the min key
//record the min key in a vector
//call removeNode to delete the Node
//repeat till the tree is empty
void problem1(LPNode Root,double* sortedvector,int& nmax)
{
double min;
//while(Root!=NULL)
for(int i=0;i<3;i++)
{
min = MAX;
sortedvector[nmax] = minValue(Root,min) ;
printf("inv%f\n",sortedvector[nmax]);
removeNode(Root,sortedvector[nmax]);
nmax++;
}
printf("The tree is empty");
}

If your function removeNode may adjust the Root, then your function is not declared properly.
void removeRootMatch(LPNode Root)
You are passing a pointer to Root. Inside the removeRootMatch function, you are working on a copy of the pointer. So code like this inside of the removeRootMatch function:
Root = tmp->Right;
tmp->Right = NULL;
delete tmp;
does not change the Root node when the function returns.
To address this issue, you should pass the Root pointer by reference:
void removeRootMatch(LPNode& Root)

Related

How to combine findMin() and delete() to remove smallest node in a BST?

I have a recRemove function that recursively removes the given node. I also have a findMin function that finds the smallest node in the BST. I'm having trouble merging the two so that I can remove the smallest(or largest) node. This is what I tried doing but it just returned garbage: Full code: https://pastebin.com/HCVsUZ4S
//remove min node in BST
node * extractMin()
{
return recRemove(root, findMin(root));
}
//delete node from tree
node * recRemove(node * root, double data)
{
//3 cases: no children, one child, 2 children
if (root == NULL)
{
return NULL;
}
else if (data < root->data)
{
root->left = recRemove(root->left, data);
}
else if(data > root->data)
{
root->right = recRemove(root->right, data);
}
else
{
if (root->right == NULL && root->left == NULL) //no children
{
delete root;
root = NULL;
return root;
}
else if(root->left == NULL) //only right child
{
temp = root;
root = root->right;
delete temp;
return root;
}
else if(root->right == NULL) //only left child
{
temp = root;
root = root->left;
delete temp;
return root;
}
else //2 children
{
temp->data = findMin(root->right);
root->data = temp->data;
root->right = recRemove(root->right, temp->data);
}
}
return root;
}
//find min node in BST
double findMin(node * p)
{
if(p == NULL)
{
return -1;
}
else
{
//in a balanced BST the minimum node is the leftmost node so,
//we traverse the left subtree until we get to the leftmost node and return and remove it.
temp = p;
while(temp->left != NULL)
{
temp = temp->left;
}
return temp->data;
}
}
sorry , can't write comments yet (will delete this later)
Where is temp defined? If it is a global variable than this is probably the issue...
Edit:
Have now seen the pasebin.....
temp is a member variable. Change it to a local variable.
Make sure to delete it before leaving the function. (best use std::unique_ptr<>)

How do I access a pointer from within a nested class?

This class's purpose is to emulate the functions of a Binary Search Tree. In the below code, I am trying to adapt it from a struct and a bunch of functions, into a wrapper class, called BST. One thing I am not sure of however, is how to access 'root' from within the node struct. Root is currently declared within the BST class.
class bst
{
public:
struct Node
{
public:
int data;
struct Node *left;
struct Node *right;
Node* FindMin(Node* root)
{
while(root->left != NULL) root = root->left;
return root;
}
Node* Insert(Node *root,int data)
{
if(root == NULL) {
root = new Node();
root->data = data;
root->left = root->right = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(data <= root->data)
root->left = Insert(root->left,data);
else
root->right = Insert(root->right,data);
return root;
}
Node* Delete(struct Node *root, int data)
{
if(root == NULL) return root;
else if(data < root->data) root->left = Delete(root->left,data);
else if (data > root->data) root->right = Delete(root->right,data);
//Value found
else {
// Case 1: No child
if(root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
//Case 2: One child
else if(root->left == NULL)
{
struct Node *temp = root;
root = root->right;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(root->right == NULL)
{
struct Node *temp = root;
root = root->left;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
// case 3: 2 children
else
{
struct Node *temp = FindMin(root->right);
root->data = temp->data;
root->right = Delete(root->right,temp->data);
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
}
return root;
}
//# of Nodes in tree
void size(Node *root)
{
//Check if end
if(root == NULL) return;
//Not end
else
{
bstSize = bstSize + 1;
size(root->left); //Visit left subtree
size(root->right); // Visit right subtree
}
}
void height(Node *root, int temp)
{
//Check if end
if(root == NULL)
{
if(temp > bstHeight)
{
bstHeight = temp;
}
return;
}
//Not end
else
{
temp = temp + 1;
height(root->left, temp); //Visit left subtree
height(root->right, temp); // Visit right subtree
}
}
//Function to visit nodes in Inorder
void show()
{
if(root == NULL) return;
show(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
show(root->right); // Visit right subtree
}
void check(Node *root)
{
//End of a 'branch'
if(root == NULL) return;
int value = 0;
value = root->data;
//Checking left subtree
if(value < root->left->data)
{
//Tree is NOT valid
valid = 0;
}
//Checking right subtree
if(value > root->right->data)
{
//Tree is NOT valid
valid = 0;
}
check(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
//check(root->right); // Visit right subtree
}
};
Node* root = NULL;
};
Specifically, in the show function. It's not as simple as putting it into Node with the rest of the functions, as root needs to be unique, and new Node is called at least once. Show will not compile in the current state, and I'm not sure where to proceed from here.
Though the comment says everything, let me give an additional hint:
When you want to keep your code as similar as possible to what you have now, try to add a constructor to the Node class that expects a pointer or reference (preferable) to the root and check, that each time you create a Node, you give the root to the constructor.
By the way, it might even be a better approach to look at some simple Node-based data structure implementations in C++, for example in the thread
Simple linked list in C++

Exception: Deletion of node in Binary Search Tree

I am getting Exception when running the BST Deletion. Below is my code snippet:
Bst::node * Bst::del(node *root, int num)
{
if (root == NULL)
{
return root;
}
else if (num < root->data)
{
root->left = del(root->left, num);
}
else if (num > root->data)
{
root->right = del(root->right, num);
}
else
{
if (root->left == NULL)
{
node * tmp = root;
root = root->right;
delete tmp;
}
else if (root->right == NULL)
{
node * tmp = root;
root = root->left;
delete tmp;
}
else if (root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
}
else
{
node *tmp = root;
tmp = findMin(root->right);
root->data = tmp->data;
root->right = del(root->right, tmp->data);
}
}
return root;
}
void Bst::del(int num)
{
del(root, num);
}
Everything works fine when I am deleting the other nodes but when I delete the root node itself then the function void Bst::del(int num) gets the garbage value from the function Bst::node * Bst::del(node *root, int num). The error gets resolved when I rewrite my function as
void Bst::del(int num)
{
root = del(root, num);
}
Question 1. Why it works when I delete the middle nodes or any other node except the root node. While debugging I found that even root was getting deleted properly when the function Bst::node * Bst::del(node *root, int num)was executing but when the call returned to the void Bst::del(int num) then the value of root was not getting retained and was garbage.
Question 2: Why the error got fixed when I stored the returned value in variable root?
While deleting a BST node using recursion, you must track the root node, which you're doing correctly as
root->left = // ... and root->right = ...
However when call reaches to caller after unwinding the stack, the root may get modified ( case when you delete the root itself )
This hopefully answers both of your questions

how to delete a Node in binary tree [duplicate]

This question already has answers here:
deletion in a binary search tree
(2 answers)
Closed 4 years ago.
The program is simple do the following step:
find min value of a binary tree;
record the min value in a vector;
delete the node with min value in the tree;
repeat 1-3 till the tree is empty.
No error is reported when run, but function removeNode is keep printf("Remove bug1!\n"); I can not find any logical mistake, so I do not understand why this happens. The structure of this function is:
'if min=key`,found it,call function removeRootMatch
else if min<root->key and 'left is not NULL`,go left
else print bug
The tree is defined as following, language is c++
typedef struct myNode* LPNode;
typedef struct myNode Node;
struct myNode
{
double key;
LPNode Left; //left subtree
LPNode Right; //right subtree
};
Main part of program is as following:
nmax is initialed as 0,
sortedvector is alloacted a vector with space as large as the total nodes in the tree,
min is initialed as 99999.
minValue will return the min value of tree.
compareDouble(a,b) will return 1 if a < b,return 2 if a > b,return 3 if equal
//remove root
void removeRootMatch(LPNode Root)
{
LPNode tmp = MakeNewNode(Root->key);
tmp->Left = Root->Left;
tmp->Right = Root->Right;
//no child
if(Root->Left==NULL && Root->Right == NULL) {
Root = NULL;
delete Root;
} else if(Root->Left==NULL && Root->Right!=NULL){ //one right child
Root = Root->Right;
tmp->Right = NULL;
delete tmp;
} else {
printf("Remove root bug!\n");
}
}
//remove a node
void removeMatch(LPNode Root,LPNode match,bool left)
{
//no child
if(match->Left==NULL && match->Right == NULL){
left==true?
Root->Left=NULL:
Root->Right=NULL;
delete match;
}
else if(match->Left==NULL && match->Right!=NULL){//one right child
left==true?
Root->Left=match->Right:
Root->Right=match->Right;
delete match;
} else {
printf("Remove root bug!\n");
}
}
//delete a node
void removeNode(LPNode Root,double min)
{
if(compareDouble(min,Root->key)==3){
removeRootMatch(Root);
}else if(compareDouble(min,Root->key)==1 && Root->Left != NULL) {
compareDouble(min,Root->key)==3 ?
removeMatch(Root,Root->Left,true):
removeNode(Root->Left,min);
}else{
printf("Remove bug1!\n");
}
}
This is the function call removeNode function.
//call minValue to find the min key
//record the min key in a vector
//call removeNode to delete the Node
//repeat till the tree is empty
void problem1(LPNode Root,double* sortedvector,int& nmax)
{
double min = MAX;
while(Root!=NULL)
{
sortedvector[nmax] = minValue(Root,min) ;
nmax++;
removeNode(Root,min);
}
printf("The tree is empty");
}
sortedvector[nmax] = minValue(Root,min) ;
removeNode(Root,sortedvector[nmax]);//change here
nmax++;
you have problem to pass the min. I am here to answer, not just read the title and vote.

Deleting in Binary Tree sulotion

After a few questions and some nice answers and friendly helpers here. I got the sulotion to my porblem with the deleting in the binary tree, i got suggested that, i can not just delet the largest number in the tree cause its may not the last or it has childrens 1 ,2 or none, so i made the code down below, i used a lot commenting hope that can help you people help me. What i actually dont know now, is how do i call this RemoveLargest() function in my public and then later in main, even though i dont know if the code will run properly.
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot) //Insert elements into the tree start.
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);
} //end.
void PrintTree(Node* theRoot) //print me the tree /start
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" \n";
PrintTree(theRoot->rChildptr);
}
} //end.
T Largest( Node* theRoot) // show me largest number /start.
{
if ( root == NULL )
{
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
{
return Largest(theRoot->rChildptr);
}
T value = theRoot->data;
return value;
} //end.
void RemoveLargest(Node* theRoot) //remove the largest priority number from tree /start.
{
Node* current; //the current tree?
Node* parent; //the parent of the current node?
current=theRoot;
// 3 cases :
// 1. We're removing a leaf node
// 2. We're removing a node with a single child
// 3. we're removing a node with 2 children
//Node with single child.
if((current->lChildptr == NULL && current->rChildptr != NULL)||(current->lChildptr != NULL && current->rChildptr == NULL))
{
if(current->lChildptr == NULL && current->rChildptr != NULL)
{
if(parent->lChildptr==current)
{
parent->lChildptr = current->rChildptr;
delete current;
}
else
{
parent->rChildptr = current->rChildptr;
delete current;
}
}
else //left child ok, no right child
{
if(parent->lChildptr==current)
{
parent->lChildptr = current->lChildptr;
delete current;
}
else
{
parent->rChildptr = current->lChildptr;
delete current;
}
}
return;
}
//We found a leaf(a node with not a single child)
if(current->lChildptr == NULL && current->rChildptr == NULL)
{
if (parent->lChildptr == current)
parent->lChildptr = NULL;
else
parent->rChildptr = NULL;
delete current;
return;
}
//Node with 2 children
// replace node with smallest value in right subtree
if (current->lChildptr != NULL && current->rChildptr != NULL)
{
Node* checkr;
checkr = current->rChildptr;
if((checkr->lChildptr == NULL)&&(checkr->rChildptr == NULL))
{
current=checkr;
delete checkr;
current->rChildptr = NULL;
}
else //right child has children
{
//if the node's right child has a left child
//Move all the way down left to locate smallest element
if ((current->rChildptr)->lChildptr != NULL)
{
Node* lcurr;
Node* lcurrp;
lcurrp = current->rChildptr;
lcurr = (current->rChildptr)->lChildptr;
while(lcurr->lChildptr != NULL)
{
lcurrp = lcurr;
lcurr = lcurr->lChildptr;
}
current->data = lcurr->data;
delete lcurr;
lcurrp->lChildptr = NULL;
}
else
{
Node* temp;
temp = current->rChildptr;
current->data = temp ->data;
current->rChildptr = temp->rChildptr;
delete temp;
}
}
return;
}
};
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
void RemoveLargest()
{
RemoveLargest();
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(4);
myBT->AddItem(2);
myBT->AddItem(3);
//for(int i = 0; i < 10; i++) //randommal tolti fel/fill with random
//myBT->AddItem(rand() % 100);
cout << "BinaryTree:" << endl; //kilistazaa a fat/ list my tree
myBT->PrintTree();
cout << "Largest element: " << myBT->Largest() << endl; //visszaadja a legnagyobb elemet/shows the largest number
myBT->RemoveLargest(); //suposed to delet the largest number
myBT->PrintTree(); //shows list again
}
edited the code, now its running, its creating the tree, shows the largest, but after i call my remove function still crashing... =/
Like I said before, I think you're making things overly complicated. You have to think of what it means that your node is the largest one, in the context of a binary search tree and the relationship between the keys in its nodes.
If a node is the largest one in the tree it cannot possibly have a right child pointer, because the right child would have to have a larger key. And then, if you know that it has at most a left child, you just replace your node with its possibly null left child, and you're done.
T ExtractLargest(Node*& n){
if (!n)
return -1;
if (n->rChildptr)
return ExtractLargest(n->rChildptr);
T result = n->data;
Node *d = n;
n = n->lChildptr;
delete d;
return result;
}