Trying to make a contains function for a binary tree.
The function looks like this:
bool contains(bt_node* top, int data) {
if (top == NULL) return false;
else {
if (data == top->data) return true;
else if (data < top->data) contains(top->left, data);
else if (data > top->data) contains(top->right, data);
}
}
The function is returning false for a value that actually is in the tree. Can anyone help?
Thanks,
Max
You forgot to return the value of the recursive calls to contains. So the return value of your function is undefined. Change it to the following to make it work:
bool contains(bt_node* top, int data) {
if (top == NULL) return false;
else {
if (data == top->data)
return true;
else if (data < top->data)
return contains(top->left, data); //you forgot to return the value
else if (data > top->data)
return contains(top->right, data);
}
}
You could have done slightly better though:
bool contains(bt_node* top, int data) {
if (top == NULL) return false;
if (data == top->data) return true;
if (data < top->data) return contains(top->left, data);
return contains(top->right, data);
}
Related
How can I check(checkV) if a value exists in Binary search tree if does I output "true" else "false"
void search(Node* root, int checkV){
if(checkV > root->data){
search(root->right, checkV);
}
if(checkV < root->data){
search(root->left, checkV);
}
if(checkV == root->data){
cout << "true"<<endl;
}
else{
cout << "false"<<endl;
}
}
If you need to use function "search", then first you should check if root points the nullptr, then if you found data and only after that you should search. Something like this:
void search(Node* root, int checkV) {
if (root->data == nullptr) {
cout << "false" << endl;
}
else if (checkV == root->data) {
cout << "true" << endl;
}
else if (checkV > root->data) {
search(root->right, checkV);
}
else {
search(root->left, checkV);
}
}
But it would be better, if you return bool from search and print result according to that
bool search(Node *root, int checkV) {
if (root == nullptr)
return false;
if (root->data == checkV)
return true;
return root->data < checkV ? check(root->left, checkV) : check(root->right, checkV);
}
I suggest you to modify your function so that it returns bool variables. To implement the function properly, think about the cases in which you don't find the node you are looking for. In such cases, eventually you will get a nullptr, that is Node* root won't point to an existing object. You can construct the if-else blocks as below.
bool search(Node* root, int checkV){
if(root == nullptr) return false;
else if(checkV > root->data) return search(root->right, checkV);
else if(checkV < root->data) return search(root->left, checkV);
else if(checkV == root->data) return true; // you can use else as well
}
// Print out true if node exists, otherwise false.
cout << search(root, 5) << endl;
I made a Binary Tree for storing 2 chars 'R' and 'B'. The inserting and printing functions work fine but while executing searching function, the pointer variable gives the error -var-create: unable to create variable object when watched under VS code's debugger tool.
Node Struct Code:
struct Node
{
Node * left;
Node * right;
char value;
bool endSeq = false;
};
BST's Search Functions:
bool search(string k)
{
int len = k.length();
bool found = false;
searchHelper(root, k, len, found);
if(found)
{
return true;
}
return false;
}
Node * searchHelper(Node * p, string k, int & len, bool & found)
{
if(p == NULL)
{
return NULL;
}
else if(len == 0)
{
if(p->endSeq)
{
found = true;
}
return p;
}
else if(k[0] < p->value || (k[0] == 'B' && k[0] == p->value))
{
string kNew = k.substr(1, --len);
if(p->endSeq)
{
found = true;
}
else
{
insertHelper(p->left, kNew, len);
}
}
else if(k[0] > p->value || (k[0] == 'R' && k[0] == p->value))
{
string kNew = k.substr(1, --len);
if(p->endSeq)
{
found = true;
}
else
{
insertHelper(p->right, kNew, len);
}
}
return p;
}
Theres a problem in your code. You have made a wrong recursive call. Instead of calling insertHelper you should call searchHelper
I am trying to turn this recursive function into a non-recursive one.This is a search function from a binary search tree. I am aware it is natural to make it recursive, but for learning purposes I would like to make it non-recursive. How could I do this? Thanks in advance!
bool Search(BstNode* root, string data) {
if (root == NULL) return false;
else if (root->data == data) return true;
else if (data <= root->data) return Search(root->left, data);
else return Search(root->right, data);
}
Here is mechanical way to make a recursive algorithm non-recursive.
bool Search(BstNode* root, string data) {
if (root == NULL) return false;
else if (root->data == data) return true;
else if (data <= root->data) return Search(root->left, data);
else return Search(root->right, data);
}
Bundle up the state (arguments and local variables):
bool Search(BstNode* root, string data) {
struct State {
BstNode* root;
string data;
};
State state{root, data};
if (state.root == NULL) return false;
else if (state.root->data == state.data) return true;
else if (data <= state.root->data) return Search(state.root->left, state.data);
else return Search(state.root->right, state.data);
}
wrap body in a loop:
bool Search(BstNode* root, string data) {
struct State {
BstNode* root;
string data;
};
State state{root, data};
while(true) {
if (state.root == NULL) return false;
else if (state.root->data == state.data) return true;
else if (data <= state.root->data) return Search(state.root->left, data);
else return Search(state.root->right, data);
}
}
Replace case where you tail-end recurse (return recursive_call) with changing state and continue:
bool Search(BstNode* root, string data) {
struct State {
BstNode* root;
string data;
};
State state{root, data};
while(true) {
if (state.root == NULL) return false;
else if (state.root->data == state.data) return true;
else if (data <= state.root->data) {
state = {state.root->left, state.data};
continue;
} else {
state = {state.root->right, state.data};
continue;
}
}
}
Now, if there are any more recursive calls that are not return recursive_call, add a manual stack of state and push/pop it instead of changing the back. Include the location of the return state as a void** in the code with labels.
This isn't required here, so I won't bother doing it.
You can usually make a recursive function in general iterative by essentially 'putting' the recursive calls onto a stack, and then using
while !stack.is_empty() do stack.pop() kind of thing
as this is essentially what a compiler will do given that recursion doesn't happen at the machine-code level
and I was trying to implement a binary searching tree:
template <typename T>
bool Tree<T>::search(TreeNode<T> *ptr, const T &key) {
if (ptr == 0) {
cout<<"No such data: "<<key<<" in the tree"<<endl;
return false;
}
else{
if (ptr->data == key) {
cout<<"Find a node whose data is "<<key<<endl;
return true;
}
else if (ptr->data < key) return search(ptr->leftPtr,key);
else return search(ptr->rightPtr,key);
}
}
But the result always returns false no matter the tree contains the key value or not.
Can u guys help me check the code? I tried debug, but still do not know.
Thank you!
Your traversal comparator for left-tree descending is backwards. As such, as soon as you incorrectly descend into the right tree you stand no chance of ever finding that value. Only the root, and root only, will ever be found correctly.
This:
if (ptr->data < key)
return search(ptr->leftPtr,key);
else
return search(ptr->rightPtr,key);
Should read like this:
if (key < ptr->data) // <== note key is LESS THAN node.
return search(ptr->leftPtr,key);
else
return search(ptr->rightPtr,key);
That said, consider this:
template <typename T>
bool Tree<T>::search(TreeNode<T> *ptr, const T &key)
{
if (ptr == 0) {
cout<<"No such data: "<<key<<" in the tree"<<endl;
return false;
}
if (key < ptr->data)
return search(ptr->leftPtr, key);
else if (ptr->data < key)
return search(ptr->rightPtr, key);
cout<<"Found a node whose data is "<< key << endl;
return true;
}
I can't figure out how this works, to my mind, once it gets to the answer it doesn't do anything with it.
Node* FindNode(Node *rootNode, int data)
{
if (!rootNode)
return NULL;
else
{
if (rootNode->data == data)
return rootNode;
else
{
FindNode(rootNode->left, data);
FindNode(rootNode->right, data);
}
}
}
It doesn't. It should be:
Node* FindNode(Node *rootNode, int data) {
if (!rootNode) {
return NULL;
}else if (rootNode->data == data) {
return rootNode;
}else if (data < rootNode->data) {
return FindNode(rootNode->left, data);
}else{
return FindNode(rootNode->right, data);
}
}
Note the extra return statements, and the extra else if clause.
EDIT — To sum up the comments below: The only reason the code you posted could be working is if an odd combination of compiler-implementation details and test data came together in your favour. You should definitely fix the problem rather than keeping the code how it was.
This is assuming that the FindNode returns on the first match.
Node* FindNode(Node *rootNode, int data)
{
Node *ptr;
if (!rootNode)
return NULL;
else
{
if (rootNode->data == data)
return rootNode;
else
{
ptr = NULL;
// if either left or right child is there
if(rootNode->left || rootNode->right)
{
// if not found in left subtree
if(NULL == (ptr = FindNode(rootNode->left, data))){
// check in right subtree
ptr = FindNode(rootNode->right, data);
}
}
return ptr;
}
}
}