Whats the difference between
return(checkBst(root->left, minvalue, root) && checkBst(root->right, root, maxvalue));
and
return(checkBst(root->left, minvalue, root));
return(checkBst(root->right, root, maxvalue));
My whole programme looks like this
bool checkBst(node *root, node * minvalue, node * maxvalue){
if(root == NULL){
return true;
}
if((minvalue && root->data <= minvalue->data) || (maxvalue && root->data >= maxvalue->data)){
return false;
}
return(checkBst(root->left, minvalue, root) && checkBst(root->right, root, maxvalue));
// return(checkBst(root->left, minvalue, root));
// return(checkBst(root->right, root, maxvalue));
}
To be frank, you cannot have a return for each of the function calls. This is because return is the last statement executed in a function before the control is given back to the calling function.
In your case, the second function is NEVER called. So, if your first function returns true, it never calls the 2nd function. Had the 2nd function result been false, the answer you get will be erroneous.
You still need to have a return statement at the end of both statements and capture the value returned by the functions.
I mean this statement:
return(checkBst(root->left, minvalue, root) && checkBst(root->right, root, maxvalue));
is equal to:
ret1 = checkBst(root->left, minvalue, root);
if(ret1)
return checkBst(root->right, root, maxvalue);
else
return false;
Recursion is not about putting everything in one line. That is just a coding style. The Comment by Pepijn Kramer and Some programmer dude talk about the optimization that you can get with writing in the same line. If the 1st half is false, you don't need to evaluate the 2nd half and that saves computation time and energy.
Recursion is about doing repetitive tasks by calling the same function within itself and using the result of it to give the final result.
In your case, Initially you send the whole tree. Then you divide the problem into 2 halves by calling the function for each of the sub-trees.
In each function call you take care of the terminal conditions. That is the first and second lines that you have. Those are the only cases where you don't call more functions. You are getting a return value.
Now, this return value should be propagated back to the calling function
Related
I am trying to return the last node of a binary heap (implemented with pointers, not an array). Here, 'last' means the bottom-most node starting from the left in this case without two children, actually the node where I am supposed to append the new node to. The insert function will bind data to a new node for insertion, then call this function to return the last node, so I can add the new node either left of right depending on the child nodes present, or not.
The problem is that the right side of the tree is always empty, and never gets past the height after root's. Seems to stick on the leftmost side, because it reaches first the exit condition from every recursion call starting from left.
The recursive function checks first the node, returns 0 if no child, returns 1 if only left child and returns 2 in case of a node having two children. Here is the function :
template<typename T>
node<T> * heap<T>::find_insert_pos (node<T> *x, int &res) {
if(find_insert_poshelper(x, res) == 0) return x;
else if(find_insert_poshelper(x, res) == 1) return x;
else {
node<T> *a = find_insert_pos(x->left, res);
if(find_insert_poshelper(a, res) != 2) return a;
else return find_insert_pos(a, res);
node<T> *b = find_insert_pos(x->right, res);
if(find_insert_poshelper(b, res) != 2) return b;
else return find_insert_pos(b, res);
}
}
I've tried to figure it out, but insertion still goes wrong. The other functions used into insertion are more than triple checked.
(By the way, 'res' is passed by reference always in the chunk of code)
I have changed the logic behind the function. Instead of only validating for children per node, I validate now if the node evaluated had children, if it does then I validate one step further each of those children, left and right, to see if any of those grand-children have children themselves.
If they don't, I will loop this for the next level following the root level 0, jumping to level 1 and so on, until one of the children nodes does not contain two children, and returning x.left or x.right, depending the case.
-- Final edit --
Hard to think about a MRE since it was more about logic. The question was posted by someone in need of practice with recursion, and it happened. All the logic changed, even for sub-functions.
But it will be required to manually assign and narrow down until three levels are full (full meaning having two children) before calling this operation, which is checking three levels down. Having this done nicely I get a beautiful heap.
I can show an attempt to a MRE of how I implemented it to be able to find the bottom node to append a new node to, but not pure since I don't put the code from the 'insert' function, which is part iterative (first three levels) and part recursive (that was the original question, to find the parent node for the new node to insert). How the insert operation goes, I create a new node dynamically and then I search for the parent node where I need to append new data to (the iterative part starts here until the 8th node of the tree is reached, path similar to BFS), then when the position is retrieved (that is, the pointer itself), I test whether for left or right insertion, as by the rules of the heap. Starting at the 8th node, the value of the parent node is set recursively as follows :
First the recursive function itself :
node * function_a (node *x, int &res) {
node *temp = function_b (x, res);
if(temp != ptr_null) return temp;
else {
if(x->L != ptr_null) function_a (x->L, res);
if(x->R != ptr_null) function_a (x->R, res);
return temp;
}
}
A sub-function :
node * function_b (node *x, int &res) {
node *a = x->L;
node *b = x->R;
int aL = function_c (a->L, res);
int aR = function_c (a->R, res);
int bL = function_c (b->L, res);
int bL = function_c (b->R, res);
if(aL != 2) return a->L;
else if(aR != 2) return a->R;
else if(bL != 2) return b->L;
else if(bR != 2) return b->R;
else return ptr_null;
}
And another :
int & function_c (node *x, int &res) {
if(x->L == ptr_null && x.R == ptr_null) return res = 0;
else if(x->L != ptr_null && x->R == ptr_null) return res = 1;
else return res = 2;
}
Since this is checking 3 levels down from x defined (in this case from the root) in function_a, I can't make it 100% recursive that way or I will get a segmentation fault. How can I improve my algorithm ?
So, we have a tree with nodes that store numbers.
{
int data;
treeNode* child;
treeNode* sibling;
treeNode(int data) :data(data), child(nullptr), sibling(nullptr) {}
treeNode() {}
};
I'm trying to check if every node stores an odd number.
Example:
1 -- 3
/ \
5 7
Here 1 is the root and the others are its children and the function is meant to return true.
private:
bool isOdd(treeNode* node)const
{
if (!node) //I think the problem might be here but I don't really know how to fix it
return true;
if (node->data % 2 == 0)
return false;
return isOdd(node->child);
return isOdd(node->sibling);
}
public:
bool isOdd()const
{
if (root->data % 2 == 0)
return false;
return isOdd(root->child);
}
As shown above, I'm using recursion, but I'm willing to use iterative approach too.
Thanks in advance!
After this line
return isOdd(node->child);
the follwoing one is ingored, because as Yksisarvinen has commented, after one return statement has been executed, the function is done, nothing else will be executed.
I.e.
return isOdd(node->sibling);
will not influence the result, i.e. the sibling is ignored.
In order to always return something influeced by both parts, you need a logic operation
return (isOdd(node->sibling) && isOdd(node->child));
On the other hand your code
if (!node) return true;
seems fine to me. If you analyse a pointer which points to nothing (without dereferencing it, good) then it makes sense to say "Nothing" cannot break the "all odd", so returning true makes sense to me.
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.
I am new to c++, from my understanding I have been thinking that if I pass address of a vector in a function call like fun(vector<int>&v) then the values don't get copied into a new vector of int, and any changes made will reflect back, and if in case of fun(vector<int> v) values get copied.
But when reading this link from geeksfrogeeks I realised that even if '&' is not there the changes on the vector made inside the function will retain after it ends.
here is the code:
/* This function prints all nodes that are distance k from a leaf node
path[] --> Store ancestors of a node
visited[] --> Stores true if a node is printed as output. A node may be k
distance away from many leaves, we want to print it once */
void kDistantFromLeafUtil(Node* node, int path[], bool visited[],
int pathLen, int k)
{
// Base case
if (node==NULL) return;
/* append this Node to the path array */
path[pathLen] = node->key;
visited[pathLen] = false;
pathLen++;
/* it's a leaf, so print the ancestor at distance k only
if the ancestor is not already printed */
if (node->left == NULL && node->right == NULL &&
pathLen-k-1 >= 0 && visited[pathLen-k-1] == false)
{
cout << path[pathLen-k-1] << " ";
visited[pathLen-k-1] = true;
return;
}
/* If not leaf node, recur for left and right subtrees */
kDistantFromLeafUtil(node->left, path, visited, pathLen, k);
kDistantFromLeafUtil(node->right, path, visited, pathLen, k);
}
The changes in the visited array made by one function are visible to the second call to KDistanceFromLeafUtil, without using '&', Is this similar to what happens in Java i.e referenced is copied ? Where did I go wrong in understanding it?
As " bool visited[]" is a pointer, it is indeed changed by your function.
If it were a bool or an int for instance, the copy or the argument would have been changed in the function but not the argument itself, and thus you would have seen no effect outside of your function.
I was trying to implement BST search method for finding a key in BST. Below is the code.
node* search_key(node **root,int key)
{
if (*root == NULL || (*root)->data == key ){
return (*root);
}
if ( key < (*root)->data ) {
search_key(&(*root)->left, key);
}
else{
search_key(&(*root)->right, key);
}
}
Above code was always returning null except for searching root node. I modified the code to the following and it is working perfectly.
Can anyone please explain the recursion involved here?
node* search_key(node **root,int key)
{
if (*root == NULL || (*root)->data == key ){
return (*root);
}
if ( key < (*root)->data ) {
return search_key(&(*root)->left, key); // note return
}
else{
return search_key(&(*root)->right, key);
}
}
In the first code snippet you have a function which is supposed to return something, but doesn't do that in some cases. That will lead to undefined behavior.
In the second snippet you actually return something in all paths of the function.
When you call same function or another function with a function it make a call of that function and when it completed call comes back to the caller function here call is coming back to caller but no result as you are not returning any result.
So after returning value to the called function it starts showing correct result.
Follow this image of factorial function for better understanding
In the binary tree there are 2 roots the left and right root. So your first condition says if you are in the last node (where root == NULL) or you find the key (value on root->data match the value of key) so, the program returns the exact block that contain the data (there it is not recursive).
if (*root == NULL || (*root)->data == key ){
return (*root);
The second condition say if the key is less than the value stored into root->data, the node go to the left root. So, the line returnsearch_key(root->left,key)` means: redo the same operation but now go to the left root.
if ( key < (*root)->data ) {
return search_key(&(*root)->left, key);
}
So, let's imagine that in the left root, the root->data is higher than the key,
so the line return search_key(root->right,key) means redo this operation but now go to the right root.
else{
return search_key(&(*root)->right, key);
}
The recursion will end only if you find the key somewhere or you check everything and you did not find anything. So remember, recursion means redo it again and again.
While implementing recursion we should always make sure that for each condition when we call the function recursively, then there should be a "return" statement so that immediate caller of a function will get the resultant value and therefore at the end of the recursion final value will be returned.
What in case if return statement is not used:
If there is no return statement, then the value computed by the current function will be discarded or unsaved so that the immediate caller won't get any value and further it will end up with undefined behaviour.