Find whether two (or 'n') particular values are present in a binary tree I have a solution to find if two values are present in a binary tree (not a BST).

I would like to know if there is


a more efficient way to do this?
a more elegant way to this?
specific improvement for the parts I've marked with comments?
a better way to generalize the solution if we have to check if some 'n' 
values (all of them) are present in tree or not?


I have a working solution mentioned in the code below but I think the same could be achieved using a more elegant and efficient code.

Note : Please assume that CheckIfValuesPresentInTree() is an API that I need to implement, so I can't change the underlying data structure.

/*The structure of a Node is as follows:
struct Node {
    int data;
    Node * right, * left;
};*/

void IsPresent(Node* p, int n1, int n2, bool&amp; f1, bool&amp; f2);

bool CheckIfValuesPresentInTree(Node* root, int n1, int n2) {
    auto f1 = bool{false};
    auto f2 = bool{false};

    IsPresent(root, n1, n2, f1, f2);

    return f1&amp;&amp;f2;
}

void IsPresent(Node* p, int n1, int n2, bool&amp; f1, bool&amp; f2) {
// Too many arguments passed to the function.
    if (!p) {
        return;
    }

    if (p-&gt;data == n1) {
        f1 = true;
    }

    if (p-&gt;data == n2) {
        f2 = true;
    }

    IsPresent(p-&gt;left, n1, n2, f1, f2);
    IsPresent(p-&gt;right, n1, n2, f1, f2);
// Second recursive call might not be needed if both n1 and n2 are found
// in 1st call.
// We can write something like below : but is there a better way ?
/*
    IsPresent(p-&gt;left, n1, n2, f1, f2);
    if (f1 &amp;&amp; f2) {
        return;
    }
    IsPresent(p-&gt;right, n1, n2, f1, f2);
*/
}
Reading the title, you want a solution that covers N values. Looking at your code, it doesn't meet that expectation. Not do I see you writing all variants from 1 to N.

As API, you have 2 options: compile time N or runtime.
If you go for the compile time, use variadic templates in the call. Otherwise, go for std::vector. As I always mess up the ..., I'll continue with the vector.

Your current approach makes good use of cache locality. Really interesting if the tree is big. Alternatively, you could check each element 1 by 1, really good for a big number of values if you expect a lot of miss matches.

What I would suggest is the following:

bool CheckIfValuesPresentInTree(Node* root, const std::vector&lt;int&gt; &amp; n) {
     auto f = std::vector&lt;bool&gt;{};
    f.resize(n.size(), false);
    IsPresent(root, n, f);

    return std::all_of(f.cbegin(), f.cend());
}

void IsPresent(Node* p, const std::vector&lt;int&gt; &amp;n, std::vector&lt;bool&gt; &amp;f) {

    if (!p) {
        return;
    }

    for (size_t i = 0; i &lt; n.size(); ++i)
    {
      if (p-&gt;data == n[I]) 
           f[I] = true;
    }

    IsPresent(p-&gt;left, n, f);
    IsPresent(p-&gt;right, n, f);
}


About your question on whether to stop searching once everything if found. Ain't an easy question, given the existing API, I wouldn't bother as it might be more expensive to check.

It can however be done by changing the way you indicate if the value is found. Instead of using the bool, you could use the n to keep track of values you still need to search.

void IsPresent(Node* p, std::vector&lt;int&gt; &amp;n) {

    if (!p) {
        return;
    }

    for (auto it = n.cbegin(); it != n.cend(); /**/)
    {
      if (p-&gt;data == *it) 
           it = n.erase(it);
     else
           ++it;
    }

    if (n.empty())
        return;

    IsPresent(p-&gt;left, n);

    if (n.empty())
         return;
    IsPresent(p-&gt;right, n);
}


The advantage of this, is that the amount of values you are checking reduces while searching. The check on whether you need to terminate becomes really cheap, at the expense of some bookkeeping.