Reputation: 2289
For an assignment I'm supposed to come up with a recursive function called all_less
which takes in a a pointer to any arbitrary tree (TN<T>*
) and a T
parameter. It returns true if all the values are less than the T parameter, otherwise it returns false.
The instance variables for my Tree
class are this:
T value;
TN<T>* left;
TN<T>* right;
And the function prototype for all_less
looks like this:
template<class T>
bool all_less(TN<T>* t, T v)
Since I have to consider an unsorted binary tree, I figured recursively going down each subtree and checking each value would work ok. After testing out this function:
template<class T>
bool all_less(TN<T>* t, T v)
{
if(v <= t->value) {
return false;
} else if(v > t->value) {
if(t->right != nullptr && t->left != nullptr) {
all_less(t->right, v);
all_less(t->left, v);
}
}
return true;
}
After having some issues with the function almost always returning true, I put some print statements before return true
and return false
to see what was happening.
As an example, lets say that we have the values 12, 15, 14, 5, in the binary tree. Running my function with using:
TN<int>* t;
std::cout << all_less(t, 15);
as input, would output this:
true
false
true
true
The end result would end up true, even though a false was returned once. How do I get it so that if it returns false, the function returns false and stops immediately? Also is there a better way to go about implementing this function? I did originally have a couple extra if-else statements to check if the right/left subtrees were null and go on from there, but those didn't seem to actually do anything.
Upvotes: 1
Views: 984
Reputation: 66371
You're ignoring the return values of the recursive calls.
The end result would end up true, even though a false was returned once.
That false
was returned from a different function call and has disappeared into the great bitbucket in the sky.
Recursive functions work exactly like any other functions - if you have
int f() { return 0:}
int g(int x) {
if (x == 0)
f();
return 1;
}
g(0)
will return 1, even though 0 was "returned once".
If g(0)
should return f()
's value, it must do it explicitly:
int g(int x) {
if (x == 0)
return f();
return 1;
}
You're also assuming that all nodes have either zero or two children.
If you adopt the convention that all items in an empty tree are smaller than the value, you can write
template<class T>
bool all_less(TN<T>* t, T v)
{
return !t
|| ( t->value < v
&& all_less(t->right, v)
&& all_less(t->left, v));
}
Upvotes: 3
Reputation: 206567
Your function:
template<class T>
bool all_less(TN<T>* t, T v)
{
if(v <= t->value) {
return false;
} else if(v > t->value) { // Why do you need this check?
if(t->right != nullptr && t->left != nullptr) {
// This is wrong because it's possible for one them to
// nullptr while the other is not.
all_less(t->right, v);
all_less(t->left, v);
// The above function calls are no op. You are calling
// the function recursively but are ignoring the return
// values.
}
}
return true;
}
This should work:
template<class T>
bool all_less(TN<T>* t, T v)
{
if(v <= t->value) {
return false;
}
if(t->right != nullptr )
{
if ( !all_less(t->right, v) )
{
return false;
}
}
if ( t->left != nullptr)
{
if ( !all_less(t->left, v) )
{
return false;
}
}
return true;
}
p.s. Untested code.
Upvotes: 0