4

I am trying to see if a value is contained in my Binary Search Tree, and I am traversing the tree using recursion. The problem is the function returns false as the last value on the call stack instead of true.

Here is pseudo code:

public boolean containsValue(Node node, Value v) {

   if (node.value.equals(v)) {
     return true;
   } 
   containsValue(node.left, v); // <- search left tree
   containsValue(node.right, v); // <- search right tree

   return false;
}

This always returns false.

However I can't do this because the second return statement is dead code:

 return containsValue(node.left, v);
 return containsValue(node.left, v);

So how would I fix this?

6 Answers 6

7

This solves the immediate problem, but is not the correct or efficient way to search a binary tree as it makes no decision about looking left or right, it just dumbly looks left and then right. Correct answer for that is here.


You want to return true if the left node contains it or (||) the right node contains it.

return containsValue(node.left, v) || containsValue(node.right, v);

And note that it will short circuit and not look in the right if the left contains it.

You can even make the whole thing:

return node.value.equals(v) ||
       containsValue(node.left, v) ||
       containsValue(node.right, v);
Sign up to request clarification or add additional context in comments.

5 Comments

This is incorrect implementation for looking through a binary search tree. By definition the values of the binary search trees are getting smaller the more left you go and larger the more right you go and this method does not utilize this property, making the search more inefficient.
@nickzoum You're quite right! I solved the immediate problem posed and didn't take in that it was an organized tree. I'll even delete once OP changes accept to you.
@Kingamere please change the accepted answer to nick's.
thanks, but you could just edit your answer so that it is correct.
@nickzoum If they don't come back and accept yours I will have to. Till then I've linked to yours.
3

There you go

public boolean containsValue(Node node, Value value){
    int result = node.value.compareTo(value);
    if(result == 0){
        return true;
    }else if(result < 0){
        if(node.left != null){
            return containsValue(node.left, v);
        }
        return false;
    }else{
        if(node.right != null){
            return containsValue(node.right, v);
        }
        return false;
    }
}

This will check how the value of the current node compares to the parameter value. If the parameter value is smaller then return the result for the left child (<0), if they are the same then return true (==0), if the pass by value is larger then return the result of the right child (>0). This will continue until a value is found or the child that needs to be searched is null.

This method fully utilizes the binary search tree since it does not check all the variables and has a an average efficiency of O(log(n)) whereas just looking through all the nodes has an average efficiency of O(n) which is much worst.

Sidenote: The method that gets the node with that value is essentially the same you just replace true with node, false with null and boolean with Node

Example:

public Node getNode(Node node, Value value){
    int result = node.value.compareTo(value);
    if(result == 0){
        return node;
    }else if(result < 0){
        if(node.left != null){
            return containsValue(node.left, v);
        }
        return null;
    }else{
        if(node.right != null){
            return containsValue(node.right, v);
        }
        return null;
    }
}

Comments

1

You can check if either branch has returned true, and pass that along before trying to return false.

public boolean containsValue(Node node, Value v) {

   if (node.value.equals(v)) {
       return true;
   } else if (containsValue(node.left, v)) {
       return true;
   } else if (containsValue(node.right, v)) {
       return true;
   }

   return false;
}

Comments

0

Some people love one-liners:

public boolean containsValue(Node node, Value v) {
    return node.value.equals(v) || containsValue(node.left, v) || containsValue(node.right, v);
}

Comments

0
  public boolean containsValue(Node node, Value v) {

   if (node.value.equals(v)) {
     return true;
   } 
   else if(containsValue(node.left, v))
     return true; // <- search left tree

   else if(containsValue(node.right, v)) // <- search right tree
    return true;

   return false;
}

Currently your function is also returning true but only for the node that matches with the search value, for all the other nodes it will return false. So while recurring backwards/ or moving up in the call stack, it ultimately returns false as the final answer. It will be correct only in the case of one node in the tree and it matches the search value.

Comments

0

The method returns false because of its recursive nature. In recursive function after finding the value, it will return the value to its parent copy of the method and that will return to its parent as per the code. We need to store the result somehow to take it to the first call of the recursive method.

In simple words, we need to store the result in a variable and return that variable as a final value from the recursive function.

For programmers, I am sharing a code to take help from and deeply understand it out.

 public boolean contains (int i){
    boolean result= false;
    boolean flag = recursiveContains(root, i, result);
    System.out.println(flag);
    return flag;
}
public boolean recursiveContains(Node root, int i, boolean result)
{
    // if root not null
    if (root != null){
        // if i value found in RandomBST
        if (root.value == i) {
            result = true; // result is used for understanding
            return result;
        }
        else if (i < root.value) {
            //if i smaller then root.value search i in leftchild
            result = recursiveContains(root.left, i, result);
        } else { 
            //if i>root.value search for i in rightchild
            result = recursiveContains(root.right, i, result);
        }
    }
    return result;
}

Further, I am adding a picture explanation of the code. But it requires concentration. I have called the above function for i=9. and shown how it returns true. It totally create 3 calls of contains method.

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.