Recursive Binary Tree Traversal Code Goes to Infinity - c++

I am trying to traverse a binary tree built with the input data from keyboard. Data is inserted to the binary tree successfully. I have a switch statement, where 'case 2' should traverse (and print) the binary tree with Inorder, Preorder and Postorder traversal algorithms using recursion respectively. However when 'case 2' is called, only the first data that should be printed regarding Inorder traversal is printed on screen; and it is also printed many times (infinite) where I need to stop the compiling operation. I would be more than happy if someone help me out with this one.
(RootPtr is the top -Level 0- node of the binary tree defined globally; and GetNode is basically an initializer function (using malloc) for type TreePtr pointers.)
Thank you all in advance.
This is the struct definition;
typedef struct treeItem
{
int data;
struct treeItem *left;
struct treeItem *right;
}Tree , *TreePtr;
These three are the traversing functions called respectively;
void inorder (TreePtr TemPtr)
{
while(TemPtr != NULL)
{
inorder((*TemPtr).left);
printf(" %d ", (*TemPtr).data);
inorder((*TemPtr).right);
}
printf("\n");
}
void preorder (TreePtr TemPtr)
{
while(TemPtr != NULL)
{
printf(" %d ", (*TemPtr).data);
preorder((*TemPtr).left);
preorder((*TemPtr).right);
}
printf("\n");
}
void postorder (TreePtr TemPtr)
{
while(TemPtr != NULL)
{
postorder((*TemPtr).left);
postorder((*TemPtr).right);
printf(" %d", (*TemPtr).data);
}
printf("\n");
}
This one is the related 'case' of the switch statement;
case 2:
TreePtr LocPtr;
GetNode(&LocPtr);
LocPtr = RootPtr;
printf("\n");
printf("Inorder traversal:");
inorder(LocPtr);
printf("Preorder traversal:");
preorder(LocPtr);
printf("Postorder traversal:");
postorder(LocPtr);
printf("\n");
break;

There shouldn't be a while loop inside your traversal functions. Recursivity will go in all nodes already.
void inorder (TreePtr TemPtr)
{
if (TemPtr != NULL) {
inorder((*TemPtr).left);
printf(" %d ", (*TemPtr).data);
inorder((*TemPtr).right);
}
printf("\n");
}
If you think about it, your TemPtr parameter isn't changing to NULL when you iterate in the loop. It would therefore be stuck in an infinite loop.
Explanation on tree traversal:
In your main, case 2, you call inorder with the root of the tree as parameter. Then we need to traverse the tree.
inorder(LocPtr);
In-order traversal is:
go to left child ... visit current node ... go to right child
We need two things in a recursive function/method: a base case, and a recursive call.
Here, our base case is if (TemPtr != NULL). When this condition is false, we know we have reached a leaf. If TemPtr indeed is a leaf, we don't go further to its children (which would throw errors).
But if TemPtr is not NULL, it means we are currently at a valid node. We must therefore follow the definition of in-order traversal (as stated previously).
We visit the left child:
inorder((*TemPtr).left); // equivalent to inorder(TemPtr->left);
we visit the current node:
printf(" %d ", (*TemPtr).data); // equivalent to printf (" %d ", TemPtr->data);
and we visit the right child:
inorder((*TemPtr).right); // equivalent to inorder(TemPtr->right);
When inorder is finished, the caller of inorder continues where it was. This process continues until inorder(LocPtr) finishes, and at this point you'll be back into the main, and your whole tree will have been traversed in-ordered.
The easiest way to visualize this is to draw the calls on a sheet of paper. Functions will stack on each other (main on the bottom), and are removed from the stack once they're finished.

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.

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

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

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);

Traversing and Printing a Binary Tree Level by Level

I am trying to traverse a binary tree built with the input data from keyboard. Data is inserted to the binary tree successfully. I have a switch statement, where 'case 4' should traverse (and print) the binary tree level by level. However I got EXC_BAD_ACCESS error. I would be more than happy if someone help me out with this one.
(RootPtr is the top -Level 0- node of the binary tree defined globally; TreeDepth() is the function calculating "Depth" of the tree where Depth defined globally and root node has depth of 0; and GetNode is basically an initializer function (using malloc) for type TreePtr pointers.)
Thank you all in advance.
Here is the relevant code:
This is the struct definition;
typedef struct treeItem
{
int data;
struct treeItem *left;
struct treeItem *right;
}Tree , *TreePtr;
This is the switch case where I call Level by Level traversing function(s);
case 4:
TreePtr temp;
GetNode(&temp);
temp = RootPtr;
printLevelOrder(temp);
printf("\n\n");
break;
These are the functions used for traversing the tree level by level;
void printGivenLevel(TreePtr TemPtr, int level)
{
if (items == 0)
return;
else
{ if(level == 0 )
{
printf(" %d", (*TemPtr).data); //the line I got ERROR
}
else
{
printGivenLevel((*TemPtr).left, (level-1));
printGivenLevel((*TemPtr).right, (level-1));
}
}
}
void printLevelOrder(TreePtr TemPtr)
{
TreeDepth();
if (items == 0)
printf("\nTree is empty.\n");
else
{
printf("Traverse level by level:");
for (int i=0; i<=Depth; i++)
{
printGivenLevel(TemPtr, i);
}
}
}
It's an off by one error. In your for loop:
for (int i=0; i<=Depth; i++)
You're traversing this loop Depth + 1 times. This means you're trying to access one more level than there actually is. In particular, in the final call of printGivenLevel, in the point in the recursion where level == 1, you're already at the bottom of the tree. You're now recursing one more time, but the pointers you pass into the next recursion level are garbage pointers (they aren't guaranteed to point to memory you're allowed to access, or even exists). So when you try to dereference them, you get an error.
One more thing: this implementation is pretty inefficient, since you're traversing the tree many times. It's better to do a breadth-first search, like kiss-o-matic mentioned. This way, you'll only traverse the tree once, which is much faster (although it does use more memory).

Calculate height of a tree

I am trying to calculate the height of a tree. I am doing it with the code written below.
#include<iostream.h>
struct tree
{
int data;
struct tree * left;
struct tree * right;
};
typedef struct tree tree;
class Tree
{
private:
int n;
int data;
int l,r;
public:
tree * Root;
Tree(int x)
{
n=x;
l=0;
r=0;
Root=NULL;
}
void create();
int height(tree * Height);
};
void Tree::create()
{
//Creting the tree structure
}
int Tree::height(tree * Height)
{
if(Height->left==NULL && Height->right==NULL)
{return 0;
}
else
{
l=height(Height->left);
r=height(Height->right);
if (l>r)
{l=l+1;
return l;
}
else
{
r=r+1;
return r;
}
}
}
int main()
{
Tree A(10);//Initializing 10 node Tree object
A.create();//Creating a 10 node tree
cout<<"The height of tree"<<A.height(A.Root);*/
}
It gives me the correct result.
But in some posts(googled page) it was suggested to do a Postorder traversal and use this height method to calculate the height. Any specific reason?
But isn't a postorder traversal precisely what you are doing? Assuming left and right are both non-null, you first do height(left), then height(right), and then some processing in the current node. That's postorder traversal according to me.
But I would write it like this:
int Tree::height(tree *node) {
if (!node) return -1;
return 1 + max(height(node->left), height(node->right));
}
Edit: depending on how you define tree height, the base case (for an empty tree) should be 0 or -1.
The code will fail in trees where at least one of the nodes has only one child:
// code snippet (space condensed for brevity)
int Tree::height(tree * Height) {
if(Height->left==NULL && Height->right==NULL) { return 0; }
else {
l=height(Height->left);
r=height(Height->right);
//...
If the tree has two nodes (the root and either a left or right child) calling the method on the root will not fulfill the first condition (at least one of the subtrees is non-empty) and it will call recursively on both children. One of them is null, but still it will dereference the null pointer to perform the if.
A correct solution is the one posted by Hans here. At any rate you have to choose what your method invariants are: either you allow calls where the argument is null and you handle that gracefully or else you require the argument to be non-null and guarantee that you do not call the method with null pointers.
The first case is safer if you do not control all entry points (the method is public as in your code) since you cannot guarantee that external code will not pass null pointers. The second solution (changing the signature to reference, and making it a member method of the tree class) could be cleaner (or not) if you can control all entry points.
The height of the tree doesn't change with the traversal. It remains constant. It's the sequence of the nodes that change depending on the traversal.
Definitions from wikipedia.
Preorder (depth-first):
Visit the root.
Traverse the left subtree.
Traverse the right subtree.
Inorder (symmetrical):
Traverse the left subtree.
Visit the root.
Traverse the right subtree.
Postorder:
Traverse the left subtree.
Traverse the right subtree.
Visit the root.
"Visit" in the definitions means "calculate height of node". Which in your case is either zero (both left and right are null) or 1 + combined height of children.
In your implementation, the traversal order doesn't matter, it would give the same results. Cant really tell you anything more than that without a link to your source stating postorder is to prefer.
Here is answer :
int Help :: heightTree (node *nodeptr)
{
if (!nodeptr)
return 0;
else
{
return 1 + max (heightTree (nodeptr->left), heightTree (nodeptr->right));
}
}