B-tree recursive search C++ - c++

This function recursively calls itself to search the Btree and returns true if the value is found, and false if it is not found. I also want it to cout "not found" one time at the end if it is not found. It works fine except that it says "not found" numerous times (everytime it goes down a level it says not found) since it calls itself.
bool lookup(int val, btnode *n) //returns true/false if value is in btree
{
if (n==NULL) return false; //empty tree
for (int i=0;i< n->count;i++) //check in present node for the val
if(n->value[i]==val)
{
flag = true;
return true;
}
//check in child node
for(int i =0;i<n->count;i++) //check for child node
{ if(val < n->value[i])
{ cout<<"checking a different node."<<endl;
lookup(val,n->child[i]);
}
}
if(val > n->value[(n->count)-1])
{
cout<<"searching a right subtree"<<endl;
lookup(val, n->child[n->count]);
}
if (flag==false)
return false;
else return true;
}
bool lookup2(int val, btnode *n)
{
if(lookup(val, n)==false)
{
cout<<"not found"<<endl;
return false;
}
else
{
cout<<"Found it"<<endl;
return true;
}
}

You probably want to make an auxiliary method that calls this lookup function, and does the printing. Something like:
bool lookup_print(int val, btnode *n) {
bool found = lookup(val, n);
if (found) {
cout << "Found it!" << endl;
} else {
cout << "Not found..." << endl;
}
return found;
}
Also, you need to make sure that your recursive calls are returning their values if they do find a node. So everywhere you recurse, you'll want something like:
bool found = lookup(val,n->child[i]);
if (found) {
return found;
}

Related

Search node recursion error binary search tree - C++

to keep this is as minimal as possible, I have a recursive binary tree function like this:
template <class T>
bool Bst<T>::searchTree(const nodeType<T>* p, const T& searchItem) const
{
if(p == nullptr)
{
cout << "Cannot search an empty tree." << endl;
return false; //If root is nullptr, that means there is no root node hence no binary tree to begin with
}
else
{
if(p->info == searchItem)
{
return true;
}
else if(p->info > searchItem)
{
return searchTree(p->rLink, searchItem);
}
else
{
return searchTree(p->lLink, searchItem);
}
//Sets the root node to the pointer current
}
}
This function is made use of by another function:
template <class T>
bool Bst<T>::searchTreeRecursive(const T& searchItem) const
{
return searchTree(root, searchItem);
}
And I use it in one of my main methods like this:
if(dateTree.searchTreeRecursive(newDate))
{
cout << "Date has been found." << endl;
}
else
{
cout << "Date not found." << endl;
}
Where newDate is an object of a class called Date, and dateTree is a binary search tree that holds dates inside it. The BST is fine after insertion because when doing traversal to output all the values are there.
My problem is, my searchTree function meets the condition that p==nullptr (p is root) and returns false, even when I know the date I've entered exists in the BST. Can anyone spot out problems with my code and help me out?
EDIT: For the very first date value in my BST, if i search for that it returns correctly. For every value after the first in the BST, its apparently nullptr.
Thanks

Find if the binary search tree has duplicated value

For binary search tree to see if the tree has duplicated value or not. I took this post order approach.
My goal was to keep the value of the current node and then use other function traverse the tree to see if there is any matching value to that current value, and if it finds any duplicate value it brings "true value". I choose to use recursion as it seems easier to track. but when I ran the program there was no output coming out.
#include "pch.h"
#include <iostream>
using namespace std;
class BSTNode {
public:
int data;
BSTNode* left;
BSTNode* right;
BSTNode() {};
};
BSTNode* newnode(int newdata) { BSTNode *curr = new BSTNode; curr->data = newdata; curr->left = curr->right = nullptr; return curr; }
void print(BSTNode* root) {
if (root != nullptr) {
print(root->left);
cout << root->data << endl;
print(root->right);
}
}
bool checking(BSTNode* parent, int val) {
if (val == parent->data){
bool left = checking(parent->left, val);
bool right = checking(parent->right, val);
return left||right;
}
else
return false;
}
bool assist(BSTNode* parent) {
if (parent != nullptr) {
assist(parent->left);
assist(parent->right);
return checking(parent, parent->data);
}
else return false;
}
int main() {
BSTNode *test = newnode(1);
test->left=newnode(2);
test->right=newnode(3);
test->left->left=newnode(2);
test->right->right=newnode(5);
print(test);
if (assist(test))
cout << "There is duplicated" << endl;
else
cout << "There is no duplicated" << endl;
return 0;
}
Your checking function should look like this:
bool checking(BSTNode* parent, int val) {
if(parent == nullptr) // point 1
return false;
if (val == parent->data){ // point 2
return true;
}
else{
bool left = checking(parent->left, val);
bool right = checking(parent->right, val);
return left||right;
}
}
Your assist function should look something like this:
bool assist(BSTNode* parent) {
if (parent != nullptr) {
if(checking(parent->left, parent->data)) return true; // point 3
if(checking(parent->right, parent->data)) return true;
return assist(parent->left)||assist(parent->right); // point 4
}
else return false;
}
You need to check for null values.
If val is same, why are you still checking? Just stop
You need to check node's value in the left and right subtree.
Recurse it for the child nodes
If you want to check that parent value is different than child values, you might do:
bool checking(const BSTNode* node, int parent_value) {
if (node == nullptr) { return false; }
if (node->data == parent_value) { return true; }
return checking(node->left, node->data)
|| checking(node->right, node->data);
}
bool assist(const BSTNode* parent) {
if (parent == nullptr) {
return false;
}
return checking(parent->left, parent->data)
|| checking(parent->right, parent->data);
}
You could just go through the BST breadth wise with a Deque. Store the values in a set and check if the value is already in the set, if it is return true otherwise wait for the loop to finish and return true. This had the benefit of hash table lookup for values at thr cost of extra storage in O(n) time. Its also easier to follow in my opinion as it's not recursion.
bool hasDuplicate(BSTNode *parent)
{
if (!parent) return false;
std::dueue<BSTNode*> nodes;
std::unordered_set<int> vals;
nodes.push_back(parent);
while(!nodes.empty()) {
BSTNode *node = nodes.pop_front();
int v = nodes->val;
// Check if value exists and return true
if(vals.find(v) != vals.end()) return true;
// Otherwise insert it
vals.insert(v);
// insert left node if exists
if (node->left) nodes.push_back(node->left);
// insert right node if exists
if (node->right) nodes.push_back(node->right);
}
// no dups found
return false;
}
Sorry for bad indents. Did this on phone lol.

Find ancestors of given node in a n-ary tree c++

Given a larg n-ary tree, I need to create a recursive function that prints all the ancestors of a leaf for example where the n-ary tree structure is given as
typedef struct sNaryNode
{
int *data;
int nchild;
struct sNaryNode **child;
} NaryNode;
Here is the function I used but that gives a wrong answer:
bool printAncestors(NaryNode *root, int *data)
{
int i=0;
if (root == NULL)
return false;
if (root->data == data)
return true;
do
{
auto b=printAncestors(root->child[i], data);
if(b)
{
cout<<*root->data<<" ";
return true;
}
else
i++;
}
while(i<root->nchild);
}
You're missing a return value at the end, and you may enter the loop and access root->child[i] even if root->nchild is zero.
Both of those will cause undefined behaviour.
I would write this with a for-loop instead:
bool printAncestors(const NaryNode *root, const int *data)
{
if (root == nullptr)
return false;
if (root->data == data)
return true;
for (int i = 0; i < root->nchild; i++)
{
if (printAncestors(root->child[i], data))
{
cout << *root->data << " ";
return true;
}
}
return false;
}

Finding an element in Binary Search Tree

I wrote this code to find a node in BST.The code works fine for Nodes found but the code crashes when a node is not found.
What is the possible error in my code?
TreeNode* fetch(TreeNode*root,int d)
{
if(root->data==d)
{
return root;
}
else if(root==NULL)
{
return NULL;
}
else if(d<root->data)
{
return fetch(root->left,d);
}
else if(d>root->data)
{
return fetch(root->right,d);
}
}
TreeNode* temp;
temp=fetch(root,d);
if(temp->data)
{
cout<<temp->data<<" FOUND";
}
else if(temp==NULL)
{
cout<<"Not Found";
}
You need to adjust your ordering in your fetch() function. Right now, it will error if root==NULL because it first checks if the data in the potentially non-existent node is equal to d. Fixed is as follows:
TreeNode* fetch(TreeNode*root,int d)
{
if(root==NULL)
{
return NULL;
}
else if(root->data==d)
{
return root;
}
else if(d<root->data)
{
return fetch(root->left,d);
}
else if(d>root->data)
{
return fetch(root->right,d);
}
}
Additionally you need to reorder your check at the bottom for the same reason:
if(temp==NULL)
{
cout<<"Not Found";
}
else
{
cout<<temp->data<<" FOUND";
}
The problem is with the sequence of conditions put in if else if ladder.
Please read the comments I have written on the lines of your code
TreeNode* fetch(TreeNode*root,int d)
{
if(root->data==d) /* if d doesn't exists, root becomes
null and dereferencing a null
gives error, i.e, null->data is
error. So, first root=null should
be checked*/
{
return root;
}
else if(root==NULL)
{
return NULL;
}
else if(d<root->data)
{
return fetch(root->left,d);
}
else if(d>root->data)
{
return fetch(root->right,d);
}
}
TreeNode* temp;
temp=fetch(root,d);
if(temp->data) // temp=NULL should be must codition
{
cout<<temp->data<<" FOUND";
}
else if(temp==NULL)
{
cout<<"Not Found";
}
You have no case if a node is a leaf. Before you call fetch(root->left,d) or fetch(root->right,d) make sure the node has a left or right element by checking if(root->(left/right) != NULL) before you call fetch again. If they do == NULL, then you can return NULL as you've navigated to the bottom of the tree and didn't find your element.

Why does this recursive function behave different than intended?

I am writing a binary tree and I am stuck on a search function that takes a value x and determines if it is a leaf in the tree or not.
Here is what I have:
bool search(Node<T>* &currentNode, const T& x) const
{
/* Base Case */
if ( currentNode != nullptr && (leaf(currentNode) == true) && currentNode->data == x )
{
return true;
}
/* Recursive Case */
else {
if (currentNode != nullptr)
{
search(currentNode->left, x);
search(currentNode->right, x);
}
//If first if condition is not met for all values then value must not exist
return false;
}
bool leaf(Node<T>* currentNode) const
{
if (currentNode != nullptr)
{
return ((currentNode->left == nullptr && currentNode->right == nullptr) ? true : false);
}
else
{
return true;
}
}
The code always returns false, why is the first IF statement never triggered?
EDIT:
Code calling search:
for (int i = 0; i < 101; i++)
if ((t.search(i) == true) ? cout << "LEAF FOUND: " << i << endl : cout << " NOT A LEAF: " << i << endl);
dealing with recursion can be tricky :D.
unless the root node is a leaf your code will always return return false
your code returns true to the function that made the call not all the way back to the original caller ( before recursion)
let's say your tree had three elements and the item was in the left leaf
so in the root node you called yourself with the left node so it returned true to the caller ( the root node) , the root node does nothing with this and just continue executing.
this can be simply solved simply by adding an if statement to check for the returned value of the functions you called
if (currentNode != nullptr)
{
if(search(currentNode->left, x)) return true;
if(search(currentNode->right, x)) return true;
}
return false;
Because you don't return the boolean from the search method back:
if (currentNode != nullptr)
{
search(currentNode->left, x);
search(currentNode->right, x);
}
You always will return false.