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
Related
I am working in C++ and have written a function but it does not stop the execution after the return statement.
BSTNode* search(BSTNode* root, int data)
{
BSTNode* newroot=root;
int count = 1;
if (root->data == data)
{
newroot=root;
count = 0;
}
else
{
search(root->left, data);
if (count != 0)
search(root->right, data);
}
return newroot;
}
How can I make it stop executing after returning the value?
Your count variable is useless and should be removed. The recursive calls to search() do not update it, so if (count != 0) is always evaluated as true.
You are also ignoring the return value of the recursive search() calls to stop the search once a matching node is found.
And you are ignoring the possibility of null pointers being present in the tree.
Try something more like this instead:
BSTNode* search(BSTNode* root, int data)
{
if (!root)
return nullptr;
if (root->data == data)
return root;
BSTNode *node = search(root->left, data);
if (!node)
node = search(root->right, data);
return node;
}
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.
I am trying to implement DSs in C++, here is a simple implementation of a Binary Search Tree Class with insert and search functions. The code compiles and gives the output as required.
Someone at codereview pointed out that the search function gives a warning and the code in the search function is broken. The warning is similar to 'not all control paths have a return statement' but I thought that is how a recursive function would look like. Is the warning a problem and how do I get rid of it? Also, how is the code broken? Thank you.
#include <stdio.h>
#include <iostream>
class BstNode{
int data;
BstNode* left;
BstNode* right;
public:
BstNode(int data)
{
this->data = data;
this->left = NULL;
this->right = NULL;
}
~BstNode();
void Insert(int data)
{
if(this->data >= data)
{
if (this->left == NULL)
this->left = new BstNode(data);
else
this->left->Insert(data);
}
else
{
if (this->right == NULL)
this->right = new BstNode(data);
else
this->right->Insert(data);
}
}
bool Search(int data)
{
if(this->data == data)
return true;
else if(this->data >= data)
{
if(this->left == NULL)
return false;
else
this->left->Search(data);
}
else
{
if(this->right == NULL)
return false;
else
this->right->Search(data);
}
}
};
int main()
{
BstNode* ptr_root = new BstNode(15);
ptr_root->Insert(10);
ptr_root->Insert(16);
int num;
std::cout<<"Enter the number: \n";
std::cin>> num;
if (ptr_root->Search(num))
std::cout<<"Found\n";
else
std::cout<<"Not Found\n";
return 0;
}
This function Search returns nothing in these paths
else
this->left->Search(data);
and
else
this->right->Search(data);
You have to write
else
return this->left->Search(data);
and
else
return this->right->Search(data);
The function can be defined with a single return statement the following way
bool Search( int data ) const
{
return ( this->data == data ) ||
( this->data >= data ? this->left && this->left->Search( data )
: this->right && this->right->Search( data ) );
}
Actually the condition
this->data >= data
may be substituted for
this->data > data
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);
}
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;
}
}
}