I wrote the following code to check if a node is in the BST:
bool BST_Node :: BST_Find(unique_ptr<BST_Node> root, int key){
if(!root || root->key == INT_MIN) return false;
if(root->key == key) return true;
else if(key < root->key) BST_Find(move(root->left), key);
else BST_Find(move(root->right), key);
}
root parameter is passed using move(bst) where bst in an unique_ptr.
The problem is when it tries to read root->key: even if the key is present in the tree, this method returns false.
I've tried to use the debugger and root can not be accessed.
Here is the code that uses this method:
auto bst = make_unique<BST_Node>();
for(int i=0; i<n; i++){
key = rand();
if(!bst->BST_Find(move(bst), key)) {
bst->BST_Insert(move(bst), key, "");
}
}
Try this
bool BST_Node :: BST_Find(unique_ptr<BST_Node> const &root, int key){
if(!root || root->key == INT_MIN) return false;
if(root->key == key) return true;
else if(key < root->key) return BST_Find(root->left, key);
else return BST_Find(root->right, key);
}
BST_Find(bst, 42) // no move
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 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
I have to check if a tree is a binary search tree. I'm doing this with an inorder traversal with a temporary array that collects the values. I have to check if the array is ascending order and if it is then I return true:
bool myisBST(Node* node, std::vector<int> v);
bool myisBST(Node* node)
{
return myisBST(node, std::vector<int>());
}
bool myisBST(Node* node, std::vector<int> v)
{
if (node)
{
if (node->left)
return myisBST(node->left, v);
v.push_back(node->data);
if (node->right)
return myisBST(node->right, v);
}
return std::is_sorted(v.begin(), v.end());
}
When binary tree is this:
50
/ \
25 75
/ \ / \
1 12 62 -99
As you can see, the -99 makes this not a binary search tree, but it is still returning true. Is there something wrong with my implementation?
Demo
Two problems:
In myisBST, you are passing v by value, not by reference, so when you pass the vector on recursively, the changes that are made to it don't change its value in the calling method. Simply change the function signature to bool myisBST(Node* node, std::vector<int>& v) to fix this.
The value you should be returning is whether the vector is sorted (as you do in the last line of your method), but instead you are returning prematurely by writing return myisBST(node->left, v); and return myisBST(node->right, v);. You're not actually interested in the return values of these methods; you're just using them to fill the vector inorder. Remove the return from both of these lines.
Following these two fixes, your method works.
First of all, you should probably pass the vector by reference or each recursive call will get a copy and thus the original vector will probably be empty.
Second, you don't even need to create the vector first and then do the check, you can just check the BST property at each node, i.e., the root must be bigger than the left child and smaller than the right child, e.g.,
bool isBST(const Node* root, vector<int>* v) {
if (!root) { return true; }
bool leftBST = true;
if (root->left) {
if (root->data > root->left->data) {
leftBST = isBST(root->left, v);
} else {
// the current node violates the BST precondition
return false;
}
}
// push the root
v->push_back(root->data);
// return false if left subtree is not a BST
if (!leftBST) return false;
if (root->right) {
if (root->data < root->right->data) {
// return whether or not the right subtree is a BST
return isBST(root->left, v);
} else {
// the current node violates the BST precondition
return false;
}
}
// everything good, this is a BST
return true;
}
C++ Program to check if tree is BST or not
struct Node
{
int data;
struct Node* left, *right;
};
bool IsBST(Node* ObjNode)
{
bool leftBST = false;
bool rightBST = false;
if( ObjNode->left != null && ObjNode-left < objNode->data)
{
leftBST = IsBST(ObjNode->left)
}
else if( ObjNode->left == null)
{
leftBST = true;
}
else if( ObjNode->left != null && ObjNode-left >= objNode->data)
{
leftBST = false;
}
if( ObjNode->left != null && ObjNode-left < objNode->data)
{
rightBST = IsBST(ObjNode->right)
}
else if( ObjNode->right == null)
{
rightBST = true;
}
else if( ObjNode->right != null && ObjNode-right >= objNode->data)
{
rightBST = false;
}
return (leftBST && rightBST );
}
In the previous solution, they are keeping a list of the inorder traversal, you really don't need it, you can keep checking with the last traversed element and keep moving forward.
Following solution is the fastest
class Solution {
int lastval = Integer.MIN_VALUE;
int count = 0;
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
boolean left = isValidBST(root.left);
if(!left){
return false;
}
int rootVal = root.val;
if(rootVal == -2147483648 && count == 0 ){
rootVal = rootVal + 1;
}
if( rootVal <= lastval){
return false;
}
count ++;
lastval = root.val;
boolean right = isValidBST(root.right);
if(!right){
return false;
}
return true;
}
}
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;
}
The code function that I'm specifically talking about is getCount(). There are several other functions that I haven't included here (such as finding the height of this binary tree and the total node count) which work just fine, with correct results. getCount() on the other hand produces segmentation fault except for the first node (the top, first node of the tree). Any ideas?
#include <string>
#include <algorithm>
#include <iostream>
class Word {
public:
std::string keyval;
long long count;
Word() {
keyval = "";
count = 0;
}
Word(std::string S) {
keyval = S;
count = 1;
}
};
class WordBST {
public:
Word node;
WordBST* left_child;
WordBST* right_child;
WordBST(std::string key);
void add(std::string key){
if (key == node.keyval){
node.count++;
}
else if (key < node.keyval){
if (left_child == NULL){
left_child = new WordBST(key);
}else {
left_child->add(key);
}
}else {
if (right_child == NULL){
right_child = new WordBST(key);
}else {
right_child->add(key);
}
}
}
long long getCount(std::string key){
if (key == node.keyval){
return (node.count);
}
else if (key < node.keyval){
left_child->getCount(key);
}else if(key > node.keyval){
right_child->getCount(key);
}else return 0;
/*else {
if (key < node.keyval){
left_child->getCount(key);
}else{
right_child->getCount(key);
}
}*/
}
};
WordBST::WordBST(std::string key) {
node = Word(key);
left_child = NULL;
right_child = NULL;
}
This is because you let your code run off the end without hitting a return statement.
long long getCount(std::string key){
if (key == node.keyval){
return (node.count);
} else if (left_child && key < node.keyval){
return left_child->getCount(key); // Added return
} else if(right_child && key > node.keyval){
return right_child->getCount(key); // Added return
}
return 0;
}
You also need to add null checks in more than one place throughout the code. Your add method has them, but your getCount does not.
I think you should write getCount() like this:
long long getCount(std::string key){
if (key == node.keyval){
return (node.count);
}
else if (key < node.keyval && left_child != NULL){
return left_child->getCount(key);
}else if(key > node.keyval && right_child != NULL){
return right_child->getCount(key);
}else return 0;
}
You do not check to see if the children of your node exist before calling their methods.