How do recursive functions do operations on a binary tree? - c++

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.

Related

How can I delete a binary tree with O(1) additional memory?

I was wondering if it's possible to delete a binary tree with O(1) additional memory, without using recursion or stacks.
I have managed to write the naive, recursive postorder traversal solution (which uses stack memory):
void deleteTreeRec(Node *root)
{
if (root == NULL) return;
deleteTreeRec(root->left);
deleteTreeRec(root->right);
cout << "Deleting node " << root->data << endl;
delete root;
}
I've heard that this can be achieved using (inorder) Morris traversal, which seems wrong, or at least counterintuitive, given the fact that tree deletion requires, as far as I understand, traversal in a postorder fashion (start by deleting the two subtrees, and only afterwards, the root). However, I haven't found any detailed description/pseudocode of the solution, hence I am trying my luck here.
If anybody could shed some light on this issue, it would be greatly appreciated. Thanks!
During the deletion the existing nodes of the binary tree can be used as a singly linked list: The nodes always using the left "link" is seen as the linked list.
To delete all nodes you simply repeat the following steps:
find the tail of the "linked list"
if right is non-null, move it to the end of the "list"
store the pointer the next element in the "list" in a temporary
replace the old head with the temporaty and repeat if the "list" is non-empty
Starting the search for the new tail at the previous tail results in the algorithm running in O(n) where n is the number of nodes in the binary tree.
void deleteTree(Node* root)
{
Node* tail = root;
while (root != nullptr)
{
// update tail
while (tail->left != nullptr)
{
tail = tail->left;
}
// move right to the end of the "list"
// needs to happen before retrieving next, since the node may only have a right subtree
tail->left = root->right;
// need to retrieve the data about the next
Node* next = root->left;
delete root;
root = next;
}
}

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

AVL Tree Rebalancing in C++

I'm working on an AVL tree. I think I've got all of the rotate functions working correctly. I have a rotateleft, rotateright, rotateleftright, and rotaterightleft function. They all take a node as a parameter.I don't know what node to pass to those parameters. Can you take a look at my AVL tree rebalance function and tell me if I have it correct, and what I need to pass to each of these functions. So far, I have the root or the top node, but i think I'm wrong. How do I tell what I need to pass to these functions?
Here is the function:
void BinaryTree::rebalance(Node *N)
{
int count = 1;
if((N->getLeft()->getHeight()) > (N->getRight()->getHeight() + 1))
{
if(N->getLeft()->getLeft()->getHeight() > N->getLeft()->getRight()->getHeight())
{
rotateRight(root);
recalculate(root, count);
}
else
{
rotateLeftRight(root);
recalculate(root, count);
}
}
else if(N->getRight()->getHeight()> N->getLeft()->getHeight() + 1)
{
if(N->getRight()->getRight()->getHeight() > N->getRight()->getLeft()->getHeight())
{
rotateLeft(root);
recalculate(root, count);
}
else
{
rotateRightLeft(root);
recalculate(root, count);
}
}
}
here is my rotate leftright
Node* BinaryTree::rotateLeftRight(Node *N)
{
Node *newNode = new Node();//declares a new Node
newNode = N->getLeft();//sets the node
N->setLeft(rotateLeft(newNode->getLeft());//sets the left subtree
recalculate(root);//recalculates the height
root->setHeight(NULL);//sets the height of the root node
return rotateRight(N);//retuns the tree rotated right
}
and here is my rotate left function.:
Node* BinaryTree::rotateLeft(Node *N)
{
Node *newNode = new Node();//declares a new node
newNode = N->getRight();//sets the new node to the right child of N
N->setRight(newNode->getLeft());//sets the right of N equal to new nodes left child
newNode->setLeft(N);//sets the left child of the new node to N
return newNode;//retuns the newNode
}
if i have the tree 50 20 10 and 15 what do i pass to the each of these functions to rebalance the tree?
There are some errors in your code that you did not do in the one you submitted in another question, that is you don't check for nullary pointers in your code:
you don't check if N is NULL at the begining of the method
you don't check in the line below (and in its symmetrical sibling) if the left and right nodes are NULL
if((N->getLeft()->getHeight()) > (N->getRight()->getHeight() + 1))
Regarding the algorithm itself, it depends on the behaviour of the rotation functions. The algorithm as described in the wikipedia entry explains that the second case in your nested if (the rotateLeftRight and rotateRightLeft methods) should perform 2 rotations. If your rotation functions are conform to that description, you should be alright.
The case of recalculate has been taken care of in an other question, but in this situation, you actually don't need to recalculate the height for the whole subtree, as you correctly told me in comments in that question. The only changing nodes are the ones whose children have been changed. You should perform that computation within each specific rotation method, since each case describe exactly which nodes get updated.

AVL find successor

This my my successor func:
int
BalancedTree::successor( TreeNode *node ) // successor is the left-most child of its right subtree,
{
TreeNode *tmp = node;
int successorVal = -1;
tmp = tmp->m_RChild;
if( NULL != tmp )
{
while( NULL != tmp->m_LChild )
tmp = tmp->m_LChild;
// now at left most child of right subtree
successorVal = tmp->m_nodeData;
}
return successorVal;
} // successor()
my instructor gave us a file filled with random data. I place all this data into the tree, the insert method works, but once the remove method starts, the successor function at some point returns the same value of the the node I'm looking for a successor for. This shouldn't be able to happen correct? is my successor function correct? If you want to see the remove method just mention it.
Your definition of successor is flawed already: if the node doesn't have a right node the successor is one of its ancestors: the first one whose left child is the node or one of its ancestors. Only if no such ancestor exists there is mo successor. Personally I would return an iterator to the node but otherwise the code seems to be OK.