Behavior of if versus while in a recursive C++ function - c++

I'm new to C++, but I bumped into this problem on HackerRank and ran into a situation that seemed strange to me (coming from R/Python/Java):
https://www.hackerrank.com/challenges/tree-preorder-traversal
To give some background, the HackerRank problem was:
Complete the preOrder function in your editor below, which has 1 parameter: a pointer to the root of a binary tree. It must print the values in the tree's preorder traversal as a single line of space-separated values.
Input Format:
Our hidden tester code passes the root node of a binary tree to your preOrder function.
Input:
6
3 5 2 1 4 6
Expected Output:
3 5 1 4 2 6
I wrote this solution, which I thought would work:
//node is defined as:
/*
struct node
{
int data;
node* left;
node* right;
};
*/
void preOrder(node *root){
while (root != NULL){
cout << root->data << " ";
preOrder(root->left);
preOrder(root->right);
}
return;
}
This code, though, never terminates and instead outputs:
3 5 1 1 1 1 1 1 1 1 1... (etc.)
What is strange and I am curious about is that if I change the while loop to the if conditional (as below) the program executes perfectly:
void preOrder(node *root){
if (root == NULL){
return;
}
cout << root->data << " ";
preOrder(root->left);
preOrder(root->right);
}
It is my understanding that both if and while ought to assess the condition each time preOrder() is called, but at some point, particularly after the 3rd iteration, the preOrder() function begins to continuously print 1 without terminating.
Any ideas, or could it be related to the main() code which I cannot see?

root can never become null within the context of the final call to preOrder.
A common mistake with recursion is to confuse variables with the same name at different levels of the stack. root from the first call to preOrder is not the same as root from the second call; rather, root from the second call is actually root->left or root->right from the first call. But as the recursion is unwinding, if you ever make it back out to the original call to preOrder, then you will once again be dealing with the original root.
When you hit a leaf node, you call preOrder with left and right which will both immediately return because the while loop will fail. Now you are back in the previous call to preorder, and root still points to the leaf node, not null. Within this context, root never changes, therefore how could it ever make it out of the while loop?

First of all,you have to see how preorder works you are using
while
than calling
preOrder(root->left);
preOrder(root->right);
but you have to store node's child in stack before calling next nodes otherwise all nodes are not not reached
// An iterative process to print preorder traversal of Binary tree
void iterativePreorder(node *root)
{
`// Base Case`
`if (root == NULL)`
`return;`
`// Create an empty stack and push root to it`
`stack<node *> nodeStack;`
`nodeStack.push(root);`
/* Pop all items one by one. Do following for every popped item
`a) print it`
`b) push its right child`
`c) push its left child`
Note that right child is pushed first so that left is processed first */
while (nodeStack.empty() == false)
{
`// Pop the top item from stack and print it`
` struct node *node = nodeStack.top();`
` printf ("%d ", node->data);`
` nodeStack.pop();`
`// Push right and left children of the popped node to stack`
` if (node->right)`
` nodeStack.push(node->right);`
`if (node->left)`
` nodeStack.push(node->left);`
}
}
here stack is used to store nodes

Related

Segmentation fault (core dumped) - Threaded Binary Search Tree

I keep getting the following error : Segmentation fault (core dumped) . I found out the line of code that is causing the problem ( marked with a comment inside of the program) . Please tell me why this error is happening and how to fix it.
I've tried to dry run my code (on paper ) and see no logical errors (from my understanding).
I have only recently got into coding and stackoverflow please guide me through how I can further improve my question , as well as my code . Thanks !
class tree
{
struct node // Creates a node for a tree
{
int data;
bool rbit,lbit; // rbit/lbit= defines if right/left child of root is present or not
node *left,*right;
};
public:
node *head,*root;
tree() // constructor initializes root and head
{
root=NULL;
head=createnode(10000);
}
node *createnode(int value)
{// Allocates memory for a node then initializes node with given value and returns that node
node *temp=new node ;
temp->data=value;
temp->lbit=0;
temp->rbit=0;
temp->left=NULL;
temp->right=NULL;
return temp;
}
void insert(node *temp,int value) // Creates binary search tree node by node
{
if(root==NULL) // Checking if tree is empty
{
root=createnode(value); //Root now points to new memory location
head->left=root;
head->lbit=1;
root->left=head;//this line gives the segmentation fault (what i thought before correction)
}
}
void inorder(node *root) // Inorder traversal of tree (this function is logically incorrect)
{
if(root==NULL)
return;
inorder(root->left);
cout<<root->data<<"\t";
inorder(root->right);
}
void getdata()//Accepts data , creates a node through insert() , displays result through inorder()
{
int data;
cout<<"Enter data"<<endl;
cin>>data;
insert(root,data);
inorder(root);
}
/*void inorder(node *root) // Working inorder code
{
if(root->lbit==1)
inorder(root->left);
cout<<root->data<<"\t";
if(root->rbit==1)
inorder(root->right);
}*/
};
int main()
{
tree t; // Tree Object
t.getdata(); // Calling getdata
return 0;
}
I think the comments section largely reflects a miscommunication. It's easy to believe that you are experiencing a crash ON that particular line.
This is not actually the case. Instead what you have done is created a loop in your tree which leads to infinite recursion by the inorder function. That causes a stack overflow which segfaults -- this would have been extremely easy to spot if you had just run your program with a debugger (such as gdb) attached.
temp = createnode(value);
if(root == NULL)
{
root = temp;
head->left = root;
head->lbit = 1;
temp->left = head;
}
Look at the loop you have just created:
head->left points to root
root->left == temp->left, which points to head
An inorder traversal will now visit:
root
head
root
head
root
head
...
Since it never gets to the end of the left-branch, the function never outputs anything before overflowing the stack and crashing.
So no, your code is not logically correct. There's a fundamental design flaw in it. You need to rethink what you are storing in your tree and why.
From the code,
root=temp; //Root now points to temp
head->left=root;
head->lbit=1;
temp->left=head;// this line gives the segmentation fault
root is not pointing to temp. temp(pointer) is assigned to root(pointer).
head's left pointer is root, and temp's left is head (which means root's left is head). so in the function "inorder",
void inorder(node *root) // Inorder traversal of tree
{
if(root==NULL) <<<<<<
return;
inorder(root->left);
cout<<root->data<<"\t";
inorder(root->right);
}
the argument node *root (left) is never NULL and the function never return.
There's not enough information on exactly how this should work (what is node.lbit for example).
The question's insert() function will not work. It's passing in a value which is immediately overwritten (among other issues). There's no explanation of what tree.head is for, so it's ignored. The fields node.lbit and node.rbit look to be superfluous flags of node.left != NULL (similarly for right). These are omitted too. The insert() is also not creating the tree properly.
void insert(int value) // Insert a value into the tree (at branch)
{
// Create a new node to insert
struct node *temp = createnode(value);
if (root == NULL) // Checking if tree is empty
{
root = temp; //Root now points to temp
}
else
{
insertAtBranch(root, temp);
}
}
// recursively find the leaf-node at which to insert the new node
void insertAtBranch(node *branch, node *new_node)
{
// to create a BST, less-than go left
if (new_node->value <= branch->value)
{
if (branch->left == NULL)
branch->left = new_node; // There's no left-branch, so it's the node
else
insertAtBranch(branch->left, new_node); // go deeper to find insertion point
}
else // greater-than go right
{
if (branch->right == NULL)
branch->right = new_node;
else
insertAtBranch(branch->right, new_node);
}
}
Imagine how a binary tree works. New nodes are only ever inserted at the edges. So you look at a given node, and decide if this new-node is less or grater than the one you're looking at (unless the tree is empty, of course).
Say the new-node.value is less than the branch-node.value, you want to branch left. Still with the same node, if it doesn't have a left-branch (node.left == NULL), the new node is the left branch. Otherwise you need to travel down the left-branch and check again.
I would have made node a class, and used a constructor to at least set the default properties and value. But that's not a big deal.

What is happening in this function?

I was looking for a method to display the contents of Binary search tree in inorder method. I found this method which seems quite popular but I cannot understand how is this recursion working. How will the code ever reach cout? Also root node is being passed into the function when called by the main function. EDIT: This is considering that "root!=NULL".
void display(struct tree *p)
{
while(p!=NULL)
{
display(p->left);
cout<<p->data;
display(p->right);
}
}
First of all, instead of while(p!=NULL) you should use if (p != null). Otherwise, you get an infinite loop in case the root node is not null.
It first displays the left subtree calling recursively display(p->left). After that it displays the node itself (cout<data) and finally the right subtree calling recursively display(p->right).
Suppose you have the following tree:
4
2 6
1 3 5
A call to display(root), results in the following function calls:
display(4)
display(2)
display(1)
display(null)
cout 1
display(null)
cout 2
display(3)
display(null)
cout 3
display(null)
cout 4
display(6)
display(5)
display(null)
cout 5
display(null)
cout 6
display(null)
When the function is called for node "1", it first displays the left subtree by calling display(p->left).
That function notices p==null returning therefore directly.
So control returns to display(1).
The next statement is cout << 1.
After that, it displays the right subtree by calling display(p->right).
That function notices p==null returning therefore directly.
So again, control returns to display(1).
At this point, display(1) has terminated and control returns to the function that called display(1), being display(2).
It finished its call to display(p->left) (being "1") and therefore executes it next statement, which is cout << 2.
The reason that the code will reach cout is that function display will not recurse all the time.
Once the parameter passed to display become NULL,that is,you have reached the leaf node of that tree, the recursion will start to trace back,the stack will start unwinding.Finally the control will return to the origin call of display.And it begins to execute the cout.
And that's why the judgement while(p!=NULL) is indispensable.

printing the contents of a Binary Search Tree recursively?

void MovieTree::printMovieInventory(MovieNode* node)
{
if(node)
{
while(node->rightChild!=NULL or node->leftChild!=NULL)
{
std::cout<<"Movie:"<<node->title<<" "<<node->quantity<<std::endl;
if(node->rightChild)
{
printMovieInventory(node->rightChild);
}
if(node->leftChild)
{
printMovieInventory(node->leftChild);
}
}
}
else
{
std::cout<<"No movies in list!"<<std::endl;
}
}
I'm not sure if this function is causing my issue or if it's my adding function but I feel as though the logic to this is correct. Am I missing something?
Edit::
My issue is that it's resulting in an infinite loop and it's not properly printing all associated children of the tree
Use of while in the function is wrong. It needs to be if. Otherwise, the function never breaks out of the while loop.
FWIW, that function can be simplified to:
void MovieTree::printMovieInventory(MovieNode* node)
{
if(node)
{
std::cout<<"Movie:"<<node->title<<" "<<node->quantity<<std::endl;
printMovieInventory(node->rightChild);
printMovieInventory(node->leftChild);
}
}
In addition to the problem with the while loop, this can also never print leaf nodes, as you don't print the node itself if it doesn't have either a left or a right child.
while(node->rightChild!=NULL or node->leftChild!=NULL)
{
std::cout<<"Movie:"<<node->title<<" "<<node->quantity<<std::endl;
it should be
if(node)
print node
if left
recurse left
if right
recurse right
Couple of Things here.
From the code as i understand, you are trying to print in a pre-order fashion.
the While Loop is unnecessary and that is what is causing the infinite loop
Lets say you have two nodes root and root->left
your function will print root, call the function recursively on root' = root->right (will not print anything this time because root'->left is NULL and root'->right is NULL). Then the function print(root') returns to its caller which is print(root). This time it will not exit out of the while Loop because the while condition is always true, ergo the infinite Loop.
you can simply do this
Print(root)
cout << root;
if(root->right != NULL)
Print(root->right);
if(root->left != NULL)
Print(root->left);
TO display "No Movies" just check if root == NULL before calling this recursive function Print(root);

replace each node of a tree with sum of all values in left side of the node without using extra integer pointer argument

Given a binary tree, I need to change the value in each node to sum of all the values in the nodes on the left side of the node. Essentially each node should have the value equal to sum of all values of nodes visited earlier to this node in in-order traversal of the tree. Important point is this has to be done without using integer pointer argument. I am able to solve it with interger pointer argument to hold sum like this. Without this integer pointer variable, How do I hold sum when I visit right side of a node from its parent.
void modifyBST(struct node *root, int *sum) {
if (root == NULL) return;
// Recur for right subtree
modifyBSTUtil(root->left, sum);
// Now *sum has sum of nodes in right subtree, add
// root->data to sum and update root->data
*sum = *sum + root->data;
root->data = *sum;
// Recur for left subtree
modifyBSTUtil(root->right, sum);
}
How do I modify this method such that int *sum can be removed.
My complete program is here click here
Example tree:
Example tree:
inorder: 4 2 5 1 6 3 7
preorder: 1 2 4 5 3 6 7
output : 4 6 11 12 18 21 28
int modify(struct node* node,int sum)
{
if (node == NULL)
return 0;
int l=modify(node->left,sum);
int r=modify(node->right,sum+l+node->data);
int x=node->data;
node->data=node->data+l+sum;
return x+l+r;
}
Call the function using statement:
modify(root,0);
Full implementation : http://ideone.com/A3ezlk
One possible solution:
Rephrasing the question, what you really want to do is set each node's sum to the previous node's sum + the value associated with that node, i.e.
noden->sum = noden-1->sum + noden->value
Right now, you are setting noden->sum when you visit noden, but the issue you are running into is you don't have easy access to noden-1->sum without passing it as a parameter. To work around this, I would suggest setting noden->sum when you DO have easy access to noden-1->sum, i.e. when you visit noden-1
Some C code to show what I mean
void modifyBST(struct node *curNode)
{
struct node* next = treeSuccessor(curNode);
if(next != NULL)
{
next->sum = curNode->sum + next->value;
modifyBST(next);
}
}
The assumption is that curNode->sum has been set before modifyBST is called for that node, which is valid for the first node (as its sum is just equal to its value) and inductively valid for all other nodes.
You would use this method by finding the first node (the one with value 4 in your example), if necessary setting sum equal to its value, and calling modifyBST with that node as the argument.
TreeSuccessor is a fairly well known algorithm, you can find pseudocode for it many places online if you need.
I think below code should work just fine. I have not tested it, just checked it manually.
I hope this helps:
int modifyBST(struct node *root) {
if (root == NULL) return 0;
root->data += modifyBSTUtil(root->left);
return (root->data + modifyBSTUtil(root->right));
}
Since your pointer argument variable sum never changes, we can easily get rid of it.
int sum;
void modifyNode(struct node *root)
{
if (!root) return;
modifyNode(root->left);
sum = root->data += sum;
modifyNode(root->right);
}
void modifyTree(struct node *root)
{
sum = 0, modifyNode(root);
}
integrated

How do recursive functions do operations on a binary tree?

I'm having trouble understanding this concept.
void preorderPrint( TreeNode *root ) {
if ( root != NULL ) { // (Otherwise, there's nothing to print.)
cout << root->item << " "; // Print the root item.
preorderPrint( root->left ); // Print items in left subtree.
preorderPrint( root->right ); // Print items in right subtree.
}
}
How does this print out the nodes in the binary tree? It seems like it just traverses the tree and does not print anything other than the root item.
Furthermore, it seems to me that the recursive functions that work with a binary tree just traverse the tree in a straight line. i.e. root->left just follows the trail going to the left most nodes and ignoring the right nodes in the left subtree. How does this work step by step?
You're missing the fact that when one function calls another function and the inner function returns, the other function resumes where it left off.
Consider a tree with a root node and a left node. The following happens:
We call preorderPrint on the root node.
That outputs the contents of the root node.
It calls preorderPrint on the left node.
This outputs the contents of the left node. It calls preorderPrint twice on NULL, which does nothing, and returns.
The original call to preorderPrint resumes, calling preorderPrint on the right pointer of the root node, which is NULL, and does nothing.