BST insert in C++ - c++

I'm learning C++ and writing a binary search tree. The following is the code I wrote for my insert method.
BSTNode * BST::Insert(const std::string & v) {
BSTNode *n = !root ? root = new BSTNode(v) : Insert_Helper(v,root);
if(n) size++;
return n;
}
BSTNode * BST::Insert_Helper(const std::string & v, BSTNode *n) {
if(!n->value.compare(v))
return NULL; // already have v
else if(n->value.compare(v) > 0) // v goes to the left
if(n->left) return Insert_Helper(v,n->left);
else return n->left = new BSTNode(v);
else // v goes to the right
if(n->right) Insert_Helper(v,n->right);
else return n->right = new BSTNode(v);
}
The bug I'm getting goes like this: It all works fine and dandy, until I try to insert a duplicate node. It doesn't add a new node, yet it increments count.
By observing in GDB, I've found that when I try to add a string that I already have, Insert_Helper works correctly and returns NULL. This value however (on my machine) is something like 0x6, which is out of bounds of course, but not 0x0 like I thought it would be. I think this causes an issue at the point where I have the if(n) statement. In this case n evaluates to true, and so increments size one more than it should.
Furthermore, at this point in my program, the nodes continue to get added correctly, but my insert function continues to return 0x6 as the address, even though they really are in valid locations in memory that I can access.
Can anyone give me any pointers as to what I might be doing wrong?

Your compiler probably should have spotted this, but this line near the end of your helper:
if(n->right) Insert_Helper(v,n->right);
You probably should return whatever Insert_Helper returns:
if(n->right) return Insert_Helper(v,n->right);

You can change if(n) size++ to if (n != NULL) size++

Related

what is wrong with this reverse linklist code?

var reverseList = function(head) {
function reverse(cur,pre){
if(!cur) return pre
next = cur.next
cur.next = pre
return reverse(next,head)
}
return reverse(head.next,head)
}
I tried a recursion way to write this,
this code output is not correct running, whats wrong with this code?
This is what i think:
If we go by your logic for let's say this case (1->2->3->null), then end result is - first node has address of second node in its 'next' & second node has address of first in its 'next'. So, a loop is formed (1->2 and 2->1). If you want to print such a list, it'll end up in an infinite loop kind of situation in an online platform.
As Thomas Mailund has correctly pointed out, null list case also needs to be covered.
I'd also suggest you to keep your variable names distinct from each other to avoid confusion.
(e.g. you used 'next' as variable name in your inner function which is used already for linked list).
Taking these factors into consideration, here's the rectified working version of your code:
var reverseList = function(head) {
var r = null;
function reverse(p, q) {
q.next = r;
r = q;
if (p == null) return q;
return reverse(p.next, p);
}
return (!head) ? head : reverse(head.next,head)
}

function that returns the number of nodes in a certain level of a binary search tree

I have to create a function getNodesatLevel that returns the number of nodes at a level, however, I'm getting a "may reach end of void function" error. This is for a Binary Search tree, and I'm required to use recursion for this function.
int TreeType::getNodesAtLevel(TreeNode * &node, int level, ItemType * mainArr)
{
int currentLevel = 0;
int NodeCount = 1;
if(currentLevel == level)
{
NodeCount++;
return NodeCount;
}
else if(currentLevel != level)
{
currentLevel++;
if(node->left != NULL)
getNodesAtLevel(node->left, level, mainArr);
if(node->right != NULL)
getNodesAtLevel(node->right, level, mainArr);
}
}
The error is basically what it says on the tin: your function can reach the end without returning a value.
To see why, let's just look at your outer if statement:
if(node->left != NULL)
//...
if(node->right != NULL)
//...
//...
What happens if both node->left and node->right are null? You don't handle this case at all. That's a bug.
Secondly (and arguably most importantly) you call yourself recursively, but don't do anything with the return value of your function. You don't return it, and you don't save it for later either. That means nothing really happens to it. It just gets lost.
Because of this, your function won't return this value at all. That creates situations in which nothing is returned.
So, to fix this, figure out what you want to do with the recursive return value of your function and either a) save it in a temporary variable, or b) simply return it. Which one you choose will depend on what you want your function to count.
Also, make sure you return a value even if both sides of the tree are NULL.

Binary search tree node removal crashing program?

I need to write the code for my own BST. All the functions work accept I don't understand why I'm having trouble deleting a node.
Here is my first version of inserting a new node:
void insert(const T& arg)
{
if (!root)//tree is empty, as to not dereference prev at end
{
root = new PbstNode<T>(arg);//constructor sets both left and right to null
return;
}
PbstNode<T>* prev;
PbstNode<T>* traversal=root;
while (traversal)
{
prev=traversal;//prev is parent only after loop ends
if (arg < traversal->data)//new data is less than, send left
traversal = traversal->left;
else//new data is greater than or equal to, send right
traversal = traversal->right;
}
if (arg < prev->data)
prev->left = new PbstNode<T>(arg);
else
prev->right = new PbstNode<T>(arg);
}//end insert
Then I was thinking about how I could do it without keeping track of the predecessor node pointer, because I think if I tried to remove a node by first searching for it like above, I'd have to know if the ptr to the node to be deleted is a left or right node, and it may also be the root.
So then I tried writing an insert function where I could get the 'real' ptr to the insertion node position, without having to use prev->left or prev->right.
void insert(const T& arg)
{
PbstNode<T>** insertPtrPtr= &root;//
PbstNode<T>* aPtr;
while (aPtr= *insertPtrPtr)
{
if (arg < aPtr->data)//new data is less than, send left
insertPtrPtr = & aPtr->left;
else//new data is greater than or equal to, send right
insertPtrPtr = & aPtr->right;//insertPtrPtr = & (*insertPtrPtr)->right;
}
//i cant use aPtr here
*insertPtrPtr = new PbstNode<T>(arg);//constructor sets both left and right to nullptr
}//end insert
The above works after testing inserting various values and searching for them.
However, then I tried writing the remove function in a similar way:
void remove(const T& arg)//
{
PbstNode<T>** delPtrPtr= &root;
PbstNode<T>* aPtr;
while (aPtr= *delPtrPtr)
{
if (arg == aPtr->data)
{
//fixTree
delete (*delPtrPtr);//makes program crash?? had to be created with new
return;
}
else if (arg < aPtr->data)
{
delPtrPtr = & aPtr->left;
}
else
{
delPtrPtr = & aPtr->right;//delPtrPtr = & (*delPtrPtr)->right;
}
}
std::cout<<"Requested removal not found in tree.\n";
}//end remove
The line delete *delPtrPtr crashes the program, but the variable pointed by *delPtrPtr had to be created with new, right? What's going on?
Any reply is appreciated.

Segfault-Iterative insert in BST

I'm trying to write a code to insert a new element in the BST iteratively. When I try to execute the code, I get a segfault. Can someone look over the code and help me correct it?
bool insert2(int item)
{
BstNode *parent;
BstNode *root=new BstNode;
cout<<root->data;
cout<<"\n";
BstNode *ptr;
int ctr=0;
//cout<<root->data;
if (root==NULL)
{
BstNode *temp=new BstNode;
temp->data=item;
temp->left=NULL;
temp->right=NULL;
root=temp;
//cout<<root->data;
return true;
}
else
{
ptr=root;
while (ptr!=NULL)
{
ctr=ctr+1;
cout<<ctr;
if (ptr->data==item)
{
cout<<ptr->data;
return false;
}
if (item < ptr->data)
{
parent=ptr;
ptr=ptr->left;
}
else
{
parent=ptr;
ptr=ptr->right;
}
}
BstNode *add=new BstNode;
add->data = item;
add->left= NULL;
add->right= NULL;
return true;
}
}
on editing out the root-> data part, the code would go into the first if block and return true, which makes me guess that my problem lies somewhere in the deceleration.
There are a number of things that you are doing wrong. First of all, as PaulMcKenzie has pointed out, you should not be creating the root at the beginning of the function. If the BST does not start out empty, the root already exists and you do not want to create a new one. Instead, the root should be a public variable (which would only allow you to have one BST), or the function should take a pointer to the root as one of the parameters. It certainly does not make sense that you create the root and then test it to see if it is NULL. Unless you ran out of memory, it would not be NULL right after you created it.
Another problem with your code is that after you find the appropriate location in the BST, you create the new node, but do not attach it to the tree. Instead, you might want to insert the following lines after you initialize add:
if(item < parent->data)
parent->left = add;
else
parent->right = add;
As far as the fact that you get a seg-fault every time you call the function, it is probably because, when you declare root, you do not initialize its right and left pointers to NULL. Therefore, the while loop does not stop when it reaches root->left or root->right. When you try to deference ptr later in the loop, you are deferencing an uninitialized pointer, resulting in a seg-fault.

Removing from a Binary Search Tree

I am trying to write a remove from a binary tree function. I'm kinda lost so I'm trying to handle it case by case, starting with if the value I'm trying to remove is in the root of the BST. To test my function, I am first calling a printcontents() function that prints all the contents of the tree, then I'm calling remove(8) [8 being the value in my root at the moment), and then calling printcontents() again. The way I'm doing it is by trying to replace the root with the "right-most" value in the left side of the tree. When I call printcontents the second time, it prints the new root value correctly, but when it continues printing the contents and reaches the point where that value used to be, it has a random long number "-572......"(although i don't think the number matters) and then my program crashes. I see my root's value is being replaced, but what happens afterwards??
Here's my remove function:
void BinarySearchTree::remove(int value) {
Node* tmp = head;
Node* tmp2 = head;
if (head->data == value && head->left != NULL) {
tmp=tmp->left;
while (tmp->right != NULL) {
tmp=tmp->right;
}
while (tmp2->right->right != NULL) {
tmp2=tmp2->right;
}
if (tmp->left == NULL) {
head->data = tmp->data;
tmp2->right = NULL;
delete tmp;
}
if (tmp->left != NULL) {
head->data = tmp->data;
tmp2->right = tmp->left;
delete tmp;
}
}
It's obviously incomplete, but I'm testing it to only handle the case in which the root is removed and replaced by the right-most value in the left side of the tree (assuming there is a left side, which there is), and I feel like logically it should be working, so perhaps it is when I "delete tmp" that things go wrong. I don't know whether posting my whole program will be necessary, but if so, let me know!
May I suggest that instead of writing out for root, why don't you treat the case as it is dealt with in CLRS : That is two distinct cases.
1. When node to be deleted is a leaf
2. When node to be deleted is non-leaf(in that case replace it with inorder successor/predecessor).
The root deletion obviously falls under the second case. This is just a suggestion.