How to add children to BST - c++

I'm trying to make/create a BST, but it doesn't seem to work properly. I've literally been sitting here for hours trying to figure out what's going on. It's gotten to the point where I've drawn a million diagrams to figure this out, yet my code fails me. I need to pass in a root node into a function. Then I need to traverse through the tree until I find that the parent string parameter of the function coincides with the tree parent node's string. If I do find it, I must insert the string into the parent, and create two new children from that parent. If I can't find the parent string, then I return false.
bool insertNode(BSTNode *n, char* parentQ, char* leftQ, char* rightQ)
{
if(n->Q == parentQ)
{
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q != parent)
{
insertNode(n->left,parentQ,leftQ,rightQ);
insertNode(n->right,parentQ,leftQ,rightQ);
}
else
return false;
}
Also I need to make another method that takes the tree that I have established, and corrects the strings. So the method modifies the parent string, if found, and looks at its children, if found, and replaces those strings with those found in the method parameters. It's sort of like adding a subtree without screwing the entire tree up. Thanks in advance!
bool changeNode(BSTNode *n,char* parentQ, char* leftQ, char* rightQ)
{
if(n->Q == leftQ)
{
n->Q = parentQ;
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q == rightQ)
{
n->Q = parentQ;
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q != leftQ)
{
changeNode(n->left,parentQ,leftQ, rightQ);
}
else if(n->Q != rightQ)
{
changeNode(n->right,parentQ,leftQ,rightQ);
}
return false;
}

You didn't even mention what the error was, example input / expected output, but shouldn't you be checking whether the current node actually has a left and right child, before calling the function with those children?
else if(n->Q != parentQ) // <--- you have a typo in this line, "parent"
{ // (and you don't even need the 'if')
insertNode(n->left,parentQ,leftQ,rightQ);
insertNode(n->right,parentQ,leftQ,rightQ);
// in this case you return nothing! corrupted return value
}
^ this seems very error-prone, especially null-pointer. You should turn it into something like:
else
{
if(n->left != NULL) // take a look at nullptr if you have C++11
if(insertNode(n->left,parentQ,leftQ,rightQ)) return true;
if(n->right != NULL)
if(insertNode(n->right,parentQ,leftQ,rightQ)) return true;
return false;
}
Otherwise your true return never gets propagated back beyond the first return, so then you're always returning false unless in the only case where the root of the tree is actually the node you were searching for.
Also, do not compare two char arrays using ==, unless n->Q is actually an std::string. You should use if(strcmp(n->Q, parentQ) == 0) otherwise.
Your second piece of code, however, is just a mess. You need to take a better look at what exactly will be happening on your else if's and see if it is actually doing what you want (hint: it isn't), as you currently only execute at most 1 of the code blocks, even if more than one condition is true.

Related

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.

If/Else statement returns

This section of code keeps throwing an error, "not all control paths return a value". I'm not entirely sure how to rewrite this so that I can fix the error. Other than the returns, this is what I need this section of code to do. Should I create a new variable that I declare within the if/else statement and then have the return for that variable right before the ending bracket?
node * LList::search(int srchKey)
{
node * p = head;
while (p != NULL)
{
if (p->key == srchKey)
{
return p;
}
else
{
return NULL;
}
p = p->next;
}
}
If head is NULL, search() will exit without reaching any return statement. The return value will be indeterminate. That is what the compiler is complaining about.
If head is not NULL, search() will check only the first node and then return a value, it will not search the whole list. Because of that, the return NULL; statement should not be inside the loop at all. It will exit search() as soon as it encounters an element that doesn't match, rather than continuing to the next element in the list.
This is similar to the problem I describe in Searching array reports "not found" even though it's found.
You should wait until the loop ends before doing return NULL;. If you get there, it means the item being searched for really wasn't found.
node * LList::search(int srchKey)
{
node * p = head;
while (p != NULL)
{
if (p->key == srchKey)
{
return p;
}
p = p->next;
}
return NULL;
}
You need another return statement after the while loop. One possible code path is that the program never enters the while loop. A simple
return NULL;
should fix it.
EDIT: Also, your loop will only ever make one pass through. I would remove the (if p == NULL) block; it is useless. I see your intent, but the way to implement it is how I described above.
when while condition is false, then you do not have return.
Add a return outside while in case you do not enter the loop.
Moreover, p = p->next; will never be executed because you exit the loop before reaching it because of if-else.
Regarding the logic, It seems to me that you do not need the else part at all. try to omit it and place return NULL before the end of the routine.

Equality operator for linked lists C++

I am trying to create a linked list class and I'm having trouble determining how to check the equality of two lists using the operator== (equality operator). How would I go about going through each node and checking if elements within them are equal in their respective positions?
bool List::operator==(const List& list2) const {
if(mySize != list2.mySize){
return false;
}
if(myFirst == list2.myFirst){
if(myFirst == NULL){
return true;
}
Node * nPtr1 = myFirst;
Node * nPtr2 = list2.myFirst;
while(nPtr1 != NULL){
//what can I do here to check the equality of each element in both lists?
}
}
}
According to your code, myFirst is a pointer, so the following is wrong:
if(myFirst == list2.myFirst)
Unless a node is equal to another node ONLY if it is the same node (pointer wise).
You have a special case when the lists are empty which you kind of captured:
if(myFirst == nullptr && list2.myFirst == nullptr)
{
return true;
}
That would be the empty case.
Otherwise, you got the while properly, and if your items (Node) can simple be compared you would do:
p = myFirst;
q = list2.myFirst;
while(p != nullptr)
{
if(*p != *q) // this is what you're asking about, right?
{
return false;
}
p = p->next; // not too sure how you have a Node separated from the List
q = q->next; // and check next/previous items...
}
return true;
Note that if nodes can only be equal if they have the same pointer then the compare becomes:
if(p != q) // this is a test of pointers instead of objects
P.S. Someone mentioned using a recursive algorithm. That's an idea and conceptually it's great. When using such in the real world, though, you notice that it can be (much) slower. It has to very heavily use the stack and with very large lists, it could break your software.
while(nPtr1 != NULL){
if(nPtr1 != nPtr2){
return false;
}
nPtr1=nPtr1->next;
nPtr2=nPtr2->next;
}
return true;
But this is the way to check if the two lists are identical (nPtr1 and nPtr2 are pointing to the same list). If you really want to compare lists by content you have to compare content like:
if(nPtr1->content != nPtr2->content)
and also change your first pointer check:
if(myFirst->content == list.myFirst->content)

Testing if a linked list is equal to each other

I have a set of numbers that are in a linked list. I want to compare them to see if they are the same numbers in a set. Here is my code right now:
bool set::equalset(set second)
{
Data *travel1, *travel2;
travel1 = top;
travel2 = second.topval(); //gets the top value for the second set
while (travel2->next != NULL && travel1->next != NULL)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
return true;
}
return false;
}
So what my code does is grab the top values for both of the sets and sets those equal to travel1/2 respectively, then while travel doesn't point to a null value in both sets, it traverses the lists and checks if values from either of the sets are in each other. If a value is not found, it sets it to false. Otherwise, it will be set to true and they are found to be equal.
However, this code only half works - you can easily break it by entering 1, 2 for the first set and 1, 2, 3 for the second set and they will be returned as equal. I would think that the third value (3) would make it return false. What is the missing link here?
Your code has several problems. First, you're not checking the last node. A loop condition like this:
while (travel2->next != NULL && travel1->next != NULL)
will break as soon as one of the enumerators reaches the last node, but never checks it. Further, it will also mean two sets of a single-node-each will always compare true.
Next, You have a hard return after only the first iteration, so there is no conceivable way this ever returned false on two sets that started with the same node value.
travel2 = travel2->next;
travel1 = travel1->next;
return true; // this doesn't belong here.
Next, you pass your parameter by-value, which means the copy constructor is being invoked. I don't know whether you implemented it or not (and if you didn't, you have an entire different problem), but there is no reason to duplicate the list just to see if it is equal to *this*. The function should take a const-reference as the parameter.
bool set::equalset(const set& second)
Finally, your exit condition is correct, but you cannot assume the lists were both exhausted. you have to verify it. You can do this by returning false if either traveler is non-null (and one of them will be if the lists are uneven.
Putting it all together:
bool set::equalset(const set& second)
{
const Data *travel1 = top;
const Data *travel2 = second.top;
while (travel1 && travel2)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
}
return !(travel1 || travel2);
}
Optimized for Sorted Lists
If you keep the lists sorted during input and removal methods, you can significantly make this easier, seen below:
bool set::equalset(const set& second)
{
const Data *travel1 = top;
const Data *travel2 = second.top;
while (travel1 && travel2 && travel1->value == travel2->value)
{
travel1 = travel1->next;
travel2 = travel2->next;
}
return !(travel1 || travel2);
}
In the situation you describe, the first set's iterator will be NULL before the third element of the second set is searched for, breaking your while loop. You may as well loop through each set independently. You could also check if both sets have the same number of elements before comparing the elements of each.
You need to adjust your return conditions because as of now, you return true if the first value in both this and second are present in each list.
Do something like this instead:
bool set::equalset(set second)
{
Data *travel1, *travel2;
travel1 = top;
travel2 = second.topval(); //gets the top value for the second set
while (travel2->next != NULL && travel1->next != NULL)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
}
return true;
}
with your code if two sets have different number of members. your loop will exit as travel1 or travel2 which has less no. of elements will point to NULL, when other is still not NULL. In your case travel1 will point to NULL and there will still elements to parse in travel2
Check by below code
bool set::equalset(set second)
{
Data *travel1, *travel2;
travel1 = top;
travel2 = second.topval(); //gets the top value for the second set
while (travel2->next != NULL && travel1->next != NULL)
{
if (!in(travel2->value)) //in checks if the value is in the set
return false;
if (!second.in(travel1->value)) //same idea here
return false;
travel2 = travel2->next;
travel1 = travel1->next;
}
if (travel2->next == NULL && travel1->next == NULL)
{
return true;
}
return false;
}
In this code for two set with elements 1 2 2 and 1 2 it will return false

Tree search function

Any node can have any number of children. To search this tree i wrote something like this
function Search(key, nodes){
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].key == key) {
return nodes[i];
}
if (nodes[i].hasOwnProperty('children')) {
return this.Search(key, nodes[i].children);
}
}
which doesn't quite work...any input?
You only recursively search the first node that has children.
You should rewrite that last conditional to something like this:
if (nodes[i].hasOwnProperty('children')) {
var node = this.Search(key, nodes[i].children);
if(node != null)
return node;
}
You also need to add a case for if the node is not found - for example, a return null at the very bottom of the function.
You seem to be missing a base case. What happens when you encounter a node that has no children and also is not the node you're looking for?
If this is Javascript, this in your code this.Search is probably what's giving you the problem. this means "the current Function object." Try replacing this.Search with just Search.