I have a class for binary nodes, a binary tree, and a binary search tree, they contain your basic tree functions, like find node, add node, remove node, get height, getnumberof nodes, and others like that. I tried to add a new function that counts the number of comparisons for finding a certain a certain node in the tree, but I've confused myself. The best I was able to do is check if the node was in the tree, but I can't figure out how to have the counter increment with each comparison. The method I'm trying to do is just difficult to translate into the code I have now. I just don't think I'm doing this right. If someone could help me out with this, I'd really apreciate it.
int counter = 0;
template<class ItemType>
ItemType BinarySearchTree<ItemType>::IsInTree(BinaryNode<ItemType>*
BinTreePtr, const ItemType& item)
{
BinaryNode<ItemType>* tmp = BinTreePtr;
counter++;
if (tmp == NULL) {
printf("Number of comparisons: \n", counter);
return 1;
}
else {
counter++;
if (&tmp->getItem == item)
{
printf("Number of comparisons: \n", counter);
return 0;
}
else {
counter++;
if (item < &tmp->g)
return IsInTree(tmp->leftChildPtr, item);
else
return IsIntree(tmp->rightChildPtr, item);
}
}
}
int main(){
BinarySearchTree<string>* tree1Ptr = new BinarySearchTree<string>();
tree1Ptr->add("10");
tree1Ptr->add("20");
tree1Ptr->add("30");
tree1Ptr->add("40");
tree1Ptr->add("50");
tree1Ptr->add("60");
tree1Ptr->add("70");
tree1Ptr->add("80");
counter = 0;
tree1Ptr->IsInTree(tree1Ptr, "10");
}
Initialise the counter value to 1 and increment counter before every comparison inside the condition to if statement
if (tmp == NULL) {
printf("Number of comparisons: \n", counter-1);
return 1;
}
else {
if (counter++ && &tmp->getItem == item)
{
printf("Number of comparisons: \n", counter-1);
return 0;
}
else {
if (counter++ && item < &tmp->g)
return IsInTree(tmp->leftChildPtr, item);
else
return IsIntree(tmp->rightChildPtr, item);
}
}
counter-1 will give you the count, hope this helps
Related
Could someone please let me know why my code isn't working? I am trying to count the number of times a given value appears in a binary tree using recursion. However, this approach is not working. I'd really appreciate some feedback and insight. Thank you.
public int valCount(int val) {
if (root == null) {
return 0;
}
return valCount(val, *root);
}
public int valCount(int val, Node *root) {
int cnt = 0;
if (root->left != null) {
if (root->data == val) {
cnt++;
}
int leftValCount = valCount(val, root->left);
}
if (root->right != null) {
if (root->data == val) {
cnt++;
}
int rightValCount = valCount(val, root->right);
}
return cnt + leftValCount + rightValCount;
}
A common mistake in recursion is to worry about stack frames other than the current one. Let the recursion do that work for you. Following this rule-of-thumb makes the code much easier to reason about.
The algorithm is simple: for each node, return 1 if the current node matches the target value else 0 if it doesn't and add the results of calling the same function on the left and right subtrees. The base case is when the function is called with a null root, return 0.
int valCount(int val, Node *root) {
if (!root) return 0;
return (root->val == val ? 1 : 0) +
valCount(val, root->left) +
valCount(val, root->right);
}
Can someone tell me why is this not working?
This seems correct to me
please someone look into this.
I am not able to find my mistake.
bool checkbst(node* root,int minValue,int maxValue)
{
if(root==NULL)
{
return true;
}
else if(((root->data)>(minValue))&&
((root->data)>(maxValue))&&
(checkbst(root->left,minValue,root->data))&&
(checkbst(root->right,root->data,maxValue)))
{
return true;
}
else
{
return false;
}
}
void isbst(node* root)
{
if( checkbst(root,INT_MIN,INT_MAX))
{
cout<<"the tree is bst";
}
}
You have a typo in checkbst, you are checking
((root->data)>(minValue))&&((root->data)>(maxValue))
while it probably should be
((root->data)>(minValue))&&((root->data)<(maxValue))
(notice the "less than" sign).
Your code verifies that the keys are inside a range, but it does not verify if the children satisfy the bst condition respect to the root. That is, the keys in the left subtree must be lesser than the root and the keys in the right one greater. You should check if the children are not null before doing any comparison involving subtrees.
This version should work:
bool checkbst(node* root, int minValue,int maxValue)
{
if (root == nullptr)
return true;
if (not (root->data >= minValue && root->data <= maxvalue))
return false;
if (root->left)
{
if (root->data < root->left->data)
if (not checkbst(root->left, minValue, maxValue))
return false;
else
return false;
}
// here the left subtree has been checked
if (root->right)
{
if (root->data < root->right->data)
return checkbst(root->right, minValue, maxValue);
else
return false;
}
return true; // everything is ok
}
I have checked your there is a small mistake code but there is a better way to do it. You just have to do the in order traversal of the given tree and store it in a array and then check if the elements in the array are sorted. If the elements are sorted then its a binary search tree else it will be a binary tree (which is a kind of basic difference between a binary tree and binary search tree).
There is a small mistake in your code
((root->data)>(maxValue))
should be
((root->data)<(maxValue))
Here is a solution that is O(n) time complexity and O(1) space. It uses in-order tree traversal to confirm that the tree is sorted according to BST rules, but it does not rely on maintaining an auxiliary array of in-order traversed Nodes. However, because it does rely on recursion it's usage of the stack (i.e. stack depth) can reach O(logn).
struct Node
{
int data;
struct Node* left;
struct Node* right;
};
bool isBSTHelper(Node* root, int& min, int& max)
{
if (nullptr == root)
{
max = numeric_limits<int>::min(); // has meaning for LHS traversal.
min = numeric_limits<int>::max(); // has meaning for RHS traversal.
return true;
}
int lhsMax;
int lhsMin;
if (!isBSTHelper(root->left, lhsMin, lhsMax) ||
lhsMax >= root->data)
{
return false;
}
int rhsMax;
int rhsMin;
if (!isBSTHelper(root->right, rhsMin, rhsMax) ||
rhsMin <= root->data)
{
return false;
}
min = std::min(lhsMin, root->data);
max = std::max(rhsMax, root->data);
return true;
}
bool isBST(Node* root)
{
int min;
int max;
return isBSTHelper(root, min, max);
}
So I tried my own solution in C++ but there is a bug in the code. That problem comes from judge.
So what I'm doing is keep adding a sum value and then check if the provided sum equals to the total sum in a leaf.
bool hasPathSum(TreeNode *root, int sum) {
stack<TreeNode*> st;
TreeNode *temp = root;
int SUM = 0;
bool hasSum = false;
st.push(temp);
while(!st.empty() && temp != NULL)
{
if(temp)
{
st.push(temp);
temp = temp->left;
}
else
{
st.pop();
temp = st.top();
SUM += temp->val;
if(SUM == sum)
hasSum = true;
temp = temp->right;
}
}
return hasSum;
}
Trivial to express recursively:
bool hasPathSum(TreeNode *node, int sum) {
if (!node) {
return sum == 0;
}
return hasPathSum(node->left, sum-node->val) ||
hasPathSum(node->right, sum-node->val);
}
If you translate this to a stack implementation, you will see some of the problems in yours. In particular, it is only at the leaves you want to check the sum (you check interior nodes). You have to adjust the sum as you go up and down the tree (you always add to it).
public static boolean hasPathSum(TreeNode node, int targetSum) {
if (node == null) return false;
targetSum-= node.val;
if (targetSum == 0 && node.left==null && node.right==null) {
return true;
}
int left = hasPathSum(node.left, targetSum);
int right = hasPathSum(node.right, targetSum;
return left || right;
}
I am writing a method to check if a given tree is a BST using the inorder traversal method. On executing this method, I get a segfault. Can someone help me correct it?
here, maximum stores the largest value in the BST, and k is initialized to 0. The BST is assumed to have unique positive values. isNull(root) checks if the current node is a null node or not.
bool check(BstNode* root)
{
if (root->data==maximum) return true;
isNull(root);
check(root->left);
if (root->data>k)
{
k=root->data;
}
else
{
return false;
}
check(root->right);
}
Every time when you call check(root->left) and check(root->right), I suppose you need to add sth to determine the left and the right branch is null or not. In your code, you just assume that there is sth in left and right branch and call the check function. I think that's the main reason.
You shouldn't need to specify the maximum value. An elegant solution can be found here
There are two approaches you can do this.
One is top-down approach, first check if current node is valid, if so, then check two subtree. This is very intuitive. you can find the code from #lerman's post:
struct TreeNode {
int data;
TreeNode *left;
TreeNode *right;
};
bool isBST(TreeNode *node, int minData, int maxData) {
if(node == NULL) return true;
if(node->data < minData || node->data > maxData) return false;
return isBST(node->left, minData, node->data) && isBST(node->right, node->data, maxData);
}
if(isBST(root, INT_MIN, INT_MAX)) {
puts("This is a BST.");
} else {
puts("This is NOT a BST!");
}
The other way is a bottom-up approach: first check left substree then right substree and check current tree at last. below is the code for this approach.
bool isValidBST(TreeNode *root) {
int mmin, mmax;
return helper(root, mmin, mmax);
}
bool helper(TreeNode* root, int& mmin, int& mmax) {
if(!root) {
mmin = INT_MAX;
mmax = INT_MIN;
return true;
}
int leftmin, leftmax, rightmin, rightmax;
if(!helper(root->left, leftmin, leftmax))
return false;
if(!helper(root->right, rightmin, rightmax))
return false;
if(root->val > leftmax && root->val < rightmin) {
mmin = min(min(leftmin, rightmin), root->val);
mmax = max(max(leftmax, rightmax), root->val);
return true;
}
else
return false;
}
You might notice that the first approach is pre-order traversal and the second approach is post-order traversal. inorder traversal in inappropriate here because it conflicts with the definition of BST.
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;
}
}