Depth of a node in binary tree - c++

I wrote the following function that returns the depth of a specific node of a binary tree. Consider the tree here: If I ask for the depth of node 5, I should get an answer of 3, from the path 1 -> 2 -> 5.
It's not working; I get 0, even though I return the height from the function.
Here "data" is the value whose depth is to be found, and root is the root node of tree. The initial value of height is 1 (the root node is level 1).
int height_target(node *root,int data,int height){ if(root==NULL) return 0;
if(root->info==data)
return height;
height_target(root->left,data,height+1);
height_target(root->right,data,height+1);
}

Most notably, your recursive branch returns nothing. Passing the height back one level isn't enough: you have to pass it all the way up the line.
You need to capture and return the maximum of the left & right subtree calls.
EDIT: remove that last sentence ...
Thus, you need to return the value from whichever call (left or right) finds the desired node. You didn't return anything. Something like:
ldepth = height_target(root->left , data, height+1);
if (ldepth > 0)
return ldepth;
rdepth = height_target(root->right, data, height+1);
if (rdepth > 0)
return rdepth;
return 0;
This will return whichever branch is successful in finding the desired node, and 0 on failure.

You aren't doing anything with the value returned from height_target.
Presumably you want something like:
return std::max(height_target(root->left,data,height+1),
height_target(root->right,data,height+1));

I think you get 0 as answwer because the condition
if(root->info==data)is never satisfied if there isn't a node with value equal to data. If you get 0 as a response it would be that the "data" you search in the binary tree there isn't.

Ok. I think i get it. Try with a function like this:
void height_target(node* root,int data,int height,int& h)
{
if(root==NULL)
return;
if(root->info==data)
h=height;
height(root->left,data,height+1,h);
height(root->right,data,height+1,h);
}
I think you supposend that there can't be two equal values in the tree

It's not working;
Here is one possible fix to your code: (updated - this code now compiles)
Summary - the last two lines of your code discard results during the 'decursion' (when recursion is unravelling).
int height_target(node* current, int data, int height)
{
int retVal = 0;
do {
if (nullptr == current)
break; // 0 indicates not found
if (current->info == data) { retVal = height; break; }
// found the node at 'height'; now de-curse
retVal = height_target (current->left, data, height+1);
if (retVal) break; // found data in left branch
retVal = height_target(current->right, data, height+1);
if(retVal) break; // found data in right branch
}while(0);
return retVal;
}
Imagine your search item is found 5 layers 'up', so that highest recursion returns 5.
At layer 4, the data was not found, so your code then searched both the left branch and right branch.
With either branch, when your code returned (from layer 5) with the value '5', your code simply discarded the result.
In this possible solution, I tested retVal after return from either left or right. Now if the return value (from layer 5) is not zero, the function will return the non-zero value; eventually popping the value off the stack all the way back 'down' to the bottom of your recursion.
Perhaps a simplified call trace can illustrate:
height_target (., ., 1); // first call, data not found at root
| height_target (., ., 2); // recursive call, data not found
| | height_target (., ., 3); // recurse, not found
| | | height_target (., ., 4); // recurse, not found
| | | | height_target (., data, 5); // found! 'decursion' begins
| | | | |
| | | | returns 5 // height 5 returns 5
| | | returns 5 // height 4 return 5
| | returns 5 // height 3 returns 5
| returns 5 // height 2 returns 5
returns 5 // height 1 returns 5
First call now returns 5.

The problem is in your understanding of what return does: it does not terminate all calls to the current function, it only ends the current iteration of said function and passes the value back to the previous stack frame.
Consider:
#include <iostream>
int f(int args) {
if (args == 3)
return args;
f(args + 1);
std::cout << args << "\n";
}
int main() {
f(0);
}
http://ideone.com/59Dl7X
Your compiler should have been warning you about the function not returning a value.
What you want is something like this:
static const size_t NODE_NOT_FOUND = 0;
size_t height_target_impl(node *root, int data, size_t height)
{
if (root == nullptr)
return NODE_NOT_FOUND;
if (root->info == data)
return height;
int branch_height = height_target_impl(root->left, data, height + 1);
if (branch_height != NODE_NOT_FOUND)
return branch_height;
return height_target_impl(root->right, data, height + 1);
}
size_t height_target(node* root, int data)
{
return height_target_impl(root, data, 1);
}
Called as:
int h = height_target(root, data);
This returns a value of 0 if the node wasn't found or a 1-based height, with 1 indicating data was found in the root node.

Related

Interpreting the return value of a recursive function of type 'int' in c++

Having trouble understanding an explanation of how to find the height of a binary search tree using a recursive function of type int.
For any binary search tree, given a pointer to the root node of the tree, where Node is defined conventionally as follows...
struct Node {
int data;
Node* left;
Node* right;
}
Node* root;
we can use the following recursive function of type int to give us the height of the binary search tree... (the function 'max' just takes two ints and returns the greater of the two)
int findHeight(Node* root){
if(root == NULL){
return -1;
}
return max(findHeight(root->left),findHeight(root->right)) + 1;
}
int max(int a, int b){
if (a > b)
return a;
else
return b;
}
My understanding is that findHeight(root->left) finds the height of the left subtree of root, findHeight(root->right) finds the height of the right subtree of root, and then max returns whichever is greater, since that will be the overall height of the tree, plus one to include the edge that connects root to that subtree.
I'm pretty new to recursion, so I decided to just unpack one of the recursive function calls and try to understand it. I wrote out findHeight(root->left) in a sort of pseudo-code way, with the word "PAUSE" in it every time the function called itself, to represent what was happening on the stack and indented the next function call to show a new stack frame... (in my sample BST the height of the left subtree was 2)
int fH(Node* root){
if(root == NULL)
return -1;
fH(root->left);
PAUSE
int fH(Node* root){
if root == NULL)
return -1;
fH(root->left);
PAUSE
int fHR(Node*root){
if (root == NULL)
return -1;
fH(root->left);
PAUSE
int fHR(Node* root){
if (root == NULL)
return -1;
fH(root->left);
PAUSE
int fHR(Node* root){
if(root==NULL)
return -1;
}
}
}
}
}
The function works correctly, but I don't understand how the return value of the function is growing from -1, which is what the final execution of the function returns, to 2. Do recursive int functions add 1 to their return value every time they return to their preceding stack frame?
I don't see anything in that short function that increments the return value of the function. The only thing I see is that it's -1 for the final call.
If anyone could try to explain this to me I would really appreciate the help. Thank you very much.
The function findHeight returns the currently found max height.
So The max call is reasonable with that in mind.
In this action reenactment we get the following function calls.
Call to node 1. We expect to find 2 more depth on the left hand side. One more on the right hand side. So max, will hopefully decide on the left hand side. max calls Node2 and node3
The call to 2 is discussed in point 4.
The call to 3 returns 0. max of -1 and -1, +1. Max is -1, add one to that.
The findHeight to node 2, will have the max of(left node (-1)), and the right node 4) Item 5 + 1.
max of -1, -1 +1 = 0. So this makes max of Point 4 evaluate to one.
So in the end the function findHeight says, this is the end of my current inspection (0 height). The previous function calls can add what ever they like to my one.
In my opinion this function can be written in a more intuitive way.
Maybe
int treeHeight(Node* node){
if (!node) // We are not a node.
return 0;
int weAreANode = 1; // Height 1.
int heightLeft = treeHeight(node->left);
int heightRight = treeHeight(node->right);
int theHighestSubtreeHeight = std::max(heightLeft, heightRight);
return weAreANode + theHighestSubtreeHeight;
}
I really just wanted to paint stuff again.
Consider this tree,
5
/ \
3 10
/ \ /
2 4 8
The function will be called with root which is 5.
Then it will be called with 3 , 2 (left child 3) and then 4 (right child 3).
2's height evaluates to max(-1, -1) + 1 = 0 and returned as the result of 3's call to findHeight(root->left). The same happens with 4.
The call to 3 (5's findHeight(root->left)) now evaluates to max(0, 0) + 1 = 1.
So 5's left child has a height of 1.
The other child (right child) follows the same process where the call to 10's left child returns a height of 0 and it's right child returns a height of -1. max(0, -1) + 1 = 1 which will be returned to 5's call to findHeight(root->right).
Now back at the top, 5's height is evaluated as max(1,1) + 1 = 2.
My understanding of your question is how is the height incremented for each recursive call of findHeight, let me know if that's not quite right.
In general in C++ there isn't specific syntax to define a function as recursive and is instead left to the programmer to use their function recursively through the arguments and return values of their function.
With this specific function it looks like the increment is happening at the end of this line:
return findHeight(max(findHeight(root->left),findHeight(root->right)) + 1;
The +1 at the end of the return function increments the recursive call explicitly, there isn't any implicit increment being done by the int function other than the fact that it returns an int.
Your pseudo-code misses what happens after the PAUSE. What's missing is
the call fH(root->right) (even if root->right is a nullptr)
computing max of the two recursive calls and
adding 1 to the result.
Particularly, the last point is essential to count the height levels of the tree.
If you add these points to your pseudo-code you may see that it resembles the structure of your specific tree.
So considering your example, let's say you have root node as 'A' and left node as 'B' and right node as 'C'. The program should return '1'-
Here is the stack trace-
findHeight(A)
findHeight(B)
POP findHeight(NULL) returns -1
The findHeight(NULL) is for the B's left node, which is NULL and returns -1
Now the stack has-
findHeight(A)
findHeight(B) max(-1, /*code yet to execute*/) + 1
POP findHeight(NULL) returns -1
The findHeight(NULL) is for the B's right node, which is NULL and returns -1.
Now the stack would be like-
findHeight(A)
POP findHeight(B) max(-1, -1) + 1 -> returns 0
At this point the control is back to your BST's root node i.e. the node 'A' and after executing right node's (Node C's) left node, the stack would be like-
findHeight(A) max(0, /*code yet to execute*/) + 1
findHeight(C)
findHeight(NULL) returns -1
The findHeight(NULL) is for the C's left node, which is NULL and returns -1
Now the stack has-
findHeight(A) max(0, /*code yet to execute*/) + 1
findHeight(C) max(-1, /*code yet to execute*/) + 1
POP findHeight(NULL) returns -1
The findHeight(NULL) is for the B's right node, which is NULL and returns -1.
Now the stack would be like-
findHeight(A) max(0, /*code yet to execute*/) + 1
POP findHeight(C) max(-1, -1) + 1 -> returns 0
After completion of findHeight(C), the control goes back to findHeight(A) and now the stack has-
findHeight(A) max(0, 0) + 1 -> returns 1
You have to add + 1 where you are explictly calling the function from your main.
There are too many things happening on that return line. Lets rewrite the code like this:
int findHeight(Node* root){
if(root == NULL){
return -1;
}
int left = findHeight(root->left);
int right = findHeight(root->right);
int maxval = max(left,right);
return maxval + 1;
}
int max(int a, int b){
if (a > b)
return a;
else
return b;
}
Now if we expand the calls you can see that at a leaf on the very bottom the left is -1 and the right is -1 and then maxval is -1 and it will return 0 (because there is nothing below the leaf). Then after that bottom call has returned 0 the maxval of the next level up will be 0 and the value returned will be 1 (because the leaf is below).
Let's look at one that only has left children a couple levels deep:
int findHeight(Node* root){
if(root == NULL) return -1; // not taken
int left = findHeight(Node* root->left){
if(root == NULL) return -1; // not taken
int left = findHeight(Node* root->left){
if(root == NULL) return -1; // not taken
int left = findHeight(Node* root->left){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // left = -1 at this point (no left children below here)
int right = findHeight(Node* root->right){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // right = -1 at this point (no right children)
int maxval = max(left,right); // left = -1, right = -1
return maxval + 1; // -1 + 1 = 0
} // left = 0 at this point (1 left child below here)
int right = findHeight(Node* root->right){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // right = -1 at this point (no right children)
int maxval = max(left,right); // left = 0, right = -1;
return maxval + 1; // 0 + 1 = 1
} // left = 1 at this point (2 left child below here)
int right = findHeight(Node* root->right){
if(root == NULL) return -1; // return here, rest of code doesn't happen
} // right = -1 at this point (no right children)
int maxval = max(left,right); // left = 1, right = -1
return maxval + 1; // 1 + 1 = 2
}

Find minimum value different than zero given some conditions

I've started learning C++ Sets and Iterators and I can't figure if I'm doing this correctly since I'm relatively new to programming.
I've created a Set of a struct with a custom comparator that puts the items in a decreasing order. Before receiving the input I don't know how many items my Set will contain. It can contain any number of items from 0 to 1000.
Here are the Setdefinitions:
typedef struct Pop {
int value_one; int node_value;
} Pop;
struct comparator {
bool operator() (const Pop& lhs, const Pop& rhs) const {
if (rhs.value_one == lhs.value_one) {
return lhs.node_value < rhs.node_value;
} else { return rhs.value_one < lhs.value_one;}
}
};
set<Pop, comparator> pop;
set<Pop>::iterator it;
And this is the algorithm. It should find a minimum value and print that value. If it does not find (the function do_some_work(...) returns 0), it should print "Zero work found!\n":
int minimum = (INT_MAX) / 2; int result;
int main(int argc, char** argv) {
//....
//After reading input and adding values to the SET gets to this part
Pop next;
Pop current;
for (it = pop.begin(); it != pop.end() && minimum != 1; it++) {
current = *it;
temp_it = it;
temp_it++;
if (temp_it != pop.end()) {
next = *temp_it;
// This function returns a integer value that can be any number from 0 to 5000.
// Besides this, it checks if the value found is less that the minimum (declared as global) and different of 0 and if so
// updates the minimum value. Even if the set as 1000 items and at the first iteration the value
// found is 1, minimum is updated with 1 and we should break out of the for loop.
result = do_some_work(current.node_value);
if (result > 0 && next.value_one < current.value_one) {
break;
}
} else {
result = do_some_work(current.node_value);
}
}
if (minimum != (INT_MAX) / 2) {
printf("%d\n", minimum);
} else {
printf("Zero work found!\n");
}
return 0;
}
Here are some possible outcomes.
If the Set is empty it should print Zero work found!
If the Set as one item and do_some_work(current.node_value) returns a value bigger than 0 it should printf("%d\n", minimum); or Zero work found! otherwise.
Imagine I have this Set (first position value_one and second position node_value:
4 2
3 6
3 7
3 8
3 10
2 34
If in the first iteration do_some_work(current.node_value) returns a value bigger than 0, since all other items value_one are smaller, it should break the loop, print the minimum and exit the program.
If in the first iteration do_some_work(current.node_value) returns 0, I advance in the Set and since there are 4 items with value_one as 3 I must analyze this 4 items because any of these can return a possible valid minimum value. If any of these updates the minimum value to 1, it should break the loop, print the minimum and exit the program.
In this case, the last item of the Set is only analysed if all other items return 0 or minimum value is set to 1.
For me this is both an algorithmic problem and a programming problem.
With this code, am I analysing all the possibilities and if minimum is 1, breaking the loop since if 1 is returned there's no need to check any other items?

getting the number of nodes in a binary search tree

So I'm working on a method that gets the number of nodes in a binary search tree, when I have 3 nodes, it gives me 3, but if I do 5 it gives me 4, what do I need to change?
int BinaryTree::size(int count, Node *leaf) const
{
if(leaf != NULL)//if we are not at a leaf
{
size(count + 1, leaf->getLeft());//recurisvly call the function and increment the count
size(count + 1, leaf->getRight());
}
else
{
return count;//return the count
}
}
int BinaryTree::size(Node *leaf) const
{
if(leaf == NULL) { //This node doesn't exist. Therefore there are no nodes in this 'subtree'
return 0;
} else { //Add the size of the left and right trees, then add 1 (which is the current node)
return size(leaf->getLeft()) + size(leaf->getRight()) + 1;
}
}
While this is a different approach, I find that is it easier to read through than what you had.
Other people have already chimed in with a correct algorithm. I'm just going to explain why your algorithm doesn't work.
The logic behind your algorithm seems to be: keep a running count value. If the leaf is null then it has no children so return the count, if the leaf is not null then recurse down the children.
This is backwards though. Because you're going to need to pass your int by reference, not value, and then not increment if it's null, increment if it's not null, and recurse.
So your original idea would work with some modifications, but Nick Mitchinson and arrows have a better way. This is your algorithm fixed so it works:
int BinaryTree::size(Node *leaf, int& count=0) const
{
if(leaf != NULL)//if we are not at a leaf
{
count++;
size(leaf->getLeft(), count);//recurisvly call the function and increment the count
size(leaf->getRight(), count);
}
return count;//return the count
}
But again, there are better ways to write this. And the other answers show them.
int BinaryTree::size(Node *n) const
{
if(!n)
return 0;
else
return size(n->getLeft()) + 1 + size(n->getRight());
}

Recursion: subset sum algorithm setting value in parameters

How do I reset the value of blockIndex to its inital state when I call the method?
Say if I call it and pass in the value 4. I check if that value is greater than 9, if not I add the element at pos(0). But in tracing my function I see that it adds all the values of the vector. I just want it to add 1 element, then when it check if it is greater than 9, and it is not, revert it back to the initial value. How do I do this?
int NumCriticalVotes :: CountCriticalVotes(Vector<int> & blocks, int blockIndex)
{
if (blockIndex >= 9 && blocks.isEmpty())
{
return 1;
}
if (blocks.isEmpty()) //Fail case
{
return 0;
} else {
int element = blocks.get(0);
Vector<int> rest = blocks;
rest.remove(0);
return CountCriticalVotes(rest, blockIndex) || CountCriticalVotes(rest, blockIndex + element);
}
}

Find nth smallest element in Binary Search Tree

I have written an algorithm for finding nth smallest element in BST but it returns root node instead of the nth smallest one. So if you input nodes in order 7 4 3 13 21 15, this algorithm after call find(root, 0) returns Node with value 7 instead of 3, and for call find(root, 1) it returns 13 instead of 4. Any thoughts ?
Binode* Tree::find(Binode* bn, int n) const
{
if(bn != NULL)
{
find(bn->l, n);
if(n-- == 0)
return bn;
find(bn->r, n);
}
else
return NULL;
}
and definition of Binode
class Binode
{
public:
int n;
Binode* l, *r;
Binode(int x) : n(x), l(NULL), r(NULL) {}
};
It is not possible to efficiently retrieve the n-th smallest element in a binary search tree by itself. However, this does become possible if you keep in each node an integer indicating the number of nodes in its entire subtree. From my generic AVL tree implementation:
static BAVLNode * BAVL_GetAt (const BAVL *o, uint64_t index)
{
if (index >= BAVL_Count(o)) {
return NULL;
}
BAVLNode *c = o->root;
while (1) {
ASSERT(c)
ASSERT(index < c->count)
uint64_t left_count = (c->link[0] ? c->link[0]->count : 0);
if (index == left_count) {
return c;
}
if (index < left_count) {
c = c->link[0];
} else {
c = c->link[1];
index -= left_count + 1;
}
}
}
In the above code, node->link[0] and node->link[1] are the left and right child of node, and node->count is the number of nodes in the entire subtree of node.
The above algorithm has O(logn) time complexity, assuming the tree is balanced. Also, if you keep these counts, another operation becomes possible - given a pointer to a node, it is possible to efficiently determine its index (the inverse of the what you asked for). In the code I linked, this operation is called BAVL_IndexOf().
Be aware that the node counts need to be updated as the tree is changed; this can be done with no (asymptotic) change in time complexity.
There are a few problems with your code:
1) find() returns a value (the correct node, assuming the function is working as intended), but you don't propagate that value up the call chain, so top-level calls don't know about the (possible) found element
.
Binode* elem = NULL;
elem = find(bn->l, n);
if (elem) return elem;
if(n-- == 0)
return bn;
elem = find(bn->r, n);
return elem; // here we don't need to test: we need to return regardless of the result
2) even though you do the decrement of n at the right place, the change does not propagate upward in the call chain. You need to pass the parameter by reference (note the & after int in the function signature), so the change is made on the original value, not on a copy of it
.
Binode* Tree::find(Binode* bn, int& n) const
I have not tested the suggested changes, but they should put you in the right direction for progress