Tree search function - tree-structure

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.

Related

Why am I unable to enter elements in the linked list while the function is working otherwise?

I wrote a program to merge two sorted linked list into one and this function was the one I used to do it but it's not working. The code of the function is as follows is as follows:
void combine(Node **temp, Node *temp_1, Node *temp_2){
while(temp_1 != NULL || temp_2 != NULL){
if(temp_1->data > temp_2->data){
push(temp, temp_2->data);
temp_2 = temp_2->next;
}
else{
push(temp, temp_1->data);
temp_1 = temp_1->next;
}
}
while(temp_1 != NULL){
push(temp, temp_1->data);
temp_1 = temp_1->next;
}
while(temp_2 != NULL){
push(temp, temp_2->data);
temp_2 = temp_2->next;
}
}
Now, this code doesn't add anything to the final linked list. If I write something like
push(temp, temp_1->data);
it will add elements just fine so the problem isn't definitely with the push function. Can someone tell me what is the problem with the above code?
The full code is in the following URL:
https://ide.geeksforgeeks.org/FZ8IS4PADE
The issue is the while condition:
while(temp_1 != NULL || temp_2 != NULL){
This will allow the execution of the body of the loop when just one of those two pointers is null, and this will result in undefined behaviour on the first statement in that body:
if(temp_1->data > temp_2->data){
The || should be an &&. This will fix your issue.
Other remarks on your code
Don't use NULL for comparing your pointer variables against, but nullptr
The use of push makes your code inefficient: at every push, your code is starting an iteration through the whole list to find the end of it. Since you actually know what is the last node (since it was created in the previous iteration of the loop) this is a waste of time. Instead, keep a reference to the tail of the list that is being created. As there is no tail at the start of the combine process, it might be useful to create a "sentinel" node that comes before the real list that will be returned.
Use better variable names. temp is not temporary at all. It is the result that the caller wants to get: this name is misleading.
Avoid code repetition. The last two loops are the same except for the list that is copied from, and this code is again similar to the parts in the main loop. So create a function that does this job of copying a node from a source list to the end of another list, and that advances both pointers.
Here is what that would look like:
void copyNode(Node **source, Node **targetTail) {
*targetTail = (*targetTail)->next = new Node((*source)->data);
*source = (*source)->next;
}
void combine(Node **result, Node *head_1, Node *head_2){
Node *sentinel = new Node(0); // Dummy
Node *current = sentinel;
while(head_1 != nullptr && head_2 != nullptr){
if(head_1->data > head_2->data){
copyNode(&head_2, &current);
}
else{
copyNode(&head_1, &current);
}
}
if (head_1 == nullptr) {
head_1 = head_2;
}
while (head_1 != NULL) {
copyNode(&head_1, &current);
}
*result = sentinel->next;
delete sentinel;
}

segmentation fault while finding merge node?

I'm working on this find merge node method on hackerrank. My approach is: while both of the nodes are not null, I want to move one of the list to their next node, that's what flag variable is for. But somehow it's giving me segmentation fault? Did I accidentally access a null variable? Someone please enlighten me. Below is my method code.
Constraint: Both lists will converge and both lists are non-NULL
int FindMergeNode(Node *headA, Node *headB)
{
// Complete this function
// Do not write the main method.
bool flag = true;
while(headA != headB){
if(flag) headA=headA->next;
else headB=headB->next;
flag = !flag;
}
return headA->data; //or headB->data;
}
You make two assumptions:
1. There exists such node.
2. The distance of this node from the beginning of each list differs by at most 1 between the two lists. You alternately move forward in one list and then check to see if you got to the same node (by address). so if list1 has no nodes before the one you are looking for, and list2 has 2 nodes before it, you won't find a match.
If I understand your question correctly, the truth is that the distance from the end of the list is the same (because their tails are the same).
Why to use flag directly use the condition to check if it is the last node
if(headA->next ==NULL)
headA=headA->next;
else if (headB->next== NULL )
headB=headB->next;
Complete solution would be something
int FindMergeNode(Node *headA, Node *headB) {
Node *currentA = headA;
Node *currentB = headB;
//Do till the two nodes are the same
while(currentA != currentB){
//If you reached the end of one list start at the beginning of the other one
//currentA
if(currentA->next == NULL){
currentA = headB;
}else{
currentA = currentA->next;
}
//currentB
if(currentB->next == NULL){
currentB = headA;
}else{
currentB = currentB->next;
}
}
return currentB->data;
}

How to replace data in a certain node in a linked list?

I have an exercise using linked lists for my class. I am fairly new to the language, but I've given it an attempt. The instructions tell us to "iterate through until NodeData is found, then replace the data using the sets."
What are "the sets" in C++? I've looked online and I couldn't find anything. The only thing I can think of is setting the nodes to point somewhere else. For example head->NULL. But is this really necessary if I am simply replacing the data? To replace the data I've tried temp->order = NEWDATA. Is that the correct implementation? It did not seem to work. Maybe it was an error in a different part of the code.
bool OrderLL::Modify(Order * NodeData) {
OrderNode *temp = head;
if (temp == NULL) {
cout << "Empty List";
}
else {
while (temp != NULL) {
if (temp->order == NodeData) {
//not sure if this is the proper way of deleting data inside a node
delete anOrder;
//HOW DO I REPLACE THE DATA IN THIS PART?
}
temp = temp->next;
}
}
return false;
}
On a side note, I really do not understand why I continue to recieve downvotes on all my questions. Is it because they're basic C++ questions? They're not so basic to me. I know this website looks down upon "offtopic/chat discussions" but I just don't understand what is wrong with my questions.
You mentioned "replace" in your question, so just taking a guess but might be you are expected to replace the node itself and not just the data. In which case, it will be something like this
if(curr_node->data == to_replace_data){
curr_node->next = new_node;
new_node->next = curr_node->next->next;
free( curr_node->next); //or return curr_node->next depending on what
// you are trying to do.
}

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.

How to add children to BST

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.