I have written a function that returns true if given binary tree is binary search tree else returns false.
bool IsBst(node* root)
{
if(root->left == NULL && root->right == NULL)
{
return true;
}
if(root->left->data <= root->data && root->right->data > root->data)
{
return (IsBst(root->left) && IsBst(root->right))
}
else
{
else false;
}
}
Is my function right?
Will this function return right answer?
I have doubt in case of if left child is null then what will this comparison root->left->data<=root->data return?(If there is NULL)
Help me to improve this!
Thanks in advance!
It should be something like
bool IsBst(const node* root, node* minNode = nullptr, node* maxNode = nullptr)
{
if (root == nullptr) {
return true;
}
if (minNode != nullptr && root->data < minNode->data)
{
return false;
}
if (maxNode != nullptr && maxNode->data < root->data)
{
return false;
}
return IsBst(root->left, minNode, root)
&& IsBst(root->right, root, maxNode);
}
If you're using C++ 17 and above, you can do it even more elegantly by using an optional class. Hence, you don't need to do nullptr checks for min and max:
bool checkBST0(const Node* root, const std::optional<int>& min, const std::optional<int>& max) {
if (root != nullptr) {
const auto data = root->data;
if ((min.has_value() && min >= data) ||
(max.has_value() && max <= data)) {
return false;
}
std::optional<int> opt(data);
return checkBST0(root->left, min, opt) && checkBST0(root->right, opt, max);
}
return true;
}
Initially, you should call this method with an optional without any value:
std::optional<int> emptyOptional;
return checkBST0(root, emptyOptional, emptyOptional);
Nope, it's not right. It would fail on this tree:
3
\
\
5
And it would give a wrong answer on this one:
4
/ \
/ \
/ \
2 6
/ \ / \
1 9 0 8
A BST is defined as a tree, whose each internal node stores a key greater than all the keys in the node’s left subtree and less than those in its right subtree (see the Wikipedia article).
So it's not enough for a 1-2-9 left subtree in my example to have a left node value less than it's root (1<2) and the right node greater than it (9>2). It should also satisfy the condition that all its nodes have values less than 4, the value in the whole tree's root.
Here is an example in C I gave in the answer to the question Pseudo code to check if binary tree is a binary search tree - not sure about the recursion:
// Test a node against its closest left-side and right-side ancestors
boolean isNodeBST(NODE *lt, NODE *node, NODE *rt)
{
if(node == NULL)
return true;
if(lt != NULL && node->key <= lt->key)
return false;
if(rt != NULL && node->key >= rt->key)
return false;
return
isNodeBST(lt, node->left, node) &&
isNodeBST(node, node->right, rt);
}
boolean isTreeBST(TREE *tree)
{
return isNodeBST( NULL, tree->root, NULL);
}
Related
My assignment is to find the sum of all nodes on each branch in a binary search tree using recursion, and compare them to a user input value. If the user input value matches a sum of one of the branches, the function should return true.
In other words, the sum of 32+24+21+14=91. The sum of 32+24+28+25=109. The sum of 32+24+28+31=115 etc. I have tried many different methods, but cant seem to figure out how to traverse each branch accurately. So far I have only been able to traverse and find the sum of the left-most branch.
I am using the method of subtracting each node from the user input value. If the value reaches 0 at a Leaf-node, then clearly the user-input matches the node-sum of that branch on the tree.
The particular points of difficulty for me are when the branch diverges, such as at the node [24] and [28]. I clearly am getting something very simple wrong, but I cant figure it out.
Below is the condensed code I've written so far, in the form of two companion methods (also required for the assignment).
public:
bool findBranchSum1(int value) throw (InvalidTreeArgument) {
if (root == nullptr)
throw InvalidTreeArgument();
return(findBranchSum(root, value));
}
private:
bool findBranchSum(NodePtr node, int value) throw (InvalidTreeArgument)
{
bool result = false;
if (root == nullptr)
throw InvalidTreeArgument();
value -= node->getElement(); //subtract current node from user-input value.
cout << "Current Value = " << value << endl; //help track value changes
if (node->getLeftSide() == nullptr && node->getRightSide() == nullptr)
{
if (value == 0)
{
result = true;
return(true);
}
else
return(false);
}
else
{
if (node->getLeftSide() != nullptr)
{
node = node->getLeftSide(); //advance to next Left node
result = findBranchSum(node, value); //recursive call using new node
}
if (node->getRightSide() != nullptr)
{
node = node->getRightSide(); //advance to next Right node
result = findBranchSum(node, value); //recursive call using new node
}
return(result);
}
}
What am I doing wrong, and how can I fix my code to find the sum of each branch on the tree? Thank you in advance. I apologize for any errors in my format, or missing information.
This is wrong:
if (node->getLeftSide() != nullptr)
{
node = node->getLeftSide(); //advance to next Left node
result = findBranchSum(node, value); //recursive call using new node
}
if (node->getRightSide() != nullptr)
{
node = node->getRightSide(); //advance to next Right node
result = findBranchSum(node, value); //recursive call using new node
}
because you move to the left and then to the right branch of the left (node is changed by your assignment), if it exists! Change to:
if (node->getLeftSide() != nullptr)
{
result = findBranchSum(node->getLeftSide(), value);
}
if (node->getRightSide() != nullptr)
{
result = findBranchSum(node->getRightSide(), value);
}
Your return value management is also broken, change it to:
if (node->getLeftSide() != nullptr)
{
result = findBranchSum(node->getLeftSide(), value);
}
if (!result && node->getRightSide() != nullptr) // cut exploration if previous was correct...
{
result = findBranchSum(node->getRightSide(), value);
}
return result;
if you need to stop at the first correct branch.
I might try something like the following.
bool IsLeaf(Node const * node) {
return node && !node->left && !node->right;
}
bool CheckPathSum(Node const * node, int const target, int const sum_so_far) {
if (!node) return false;
int const sum = sum_so_far + node->element;
if IsLeaf(node) && (sum == target) return true;
return CheckPathSum(node->left, target, sum) ||
CheckPathSum(node->right, target, sum);
}
Call as
CheckPathSum(root, target, 0);
In Java, i tried this-
private static void branchSumsUtil(TreeNode root, List<Integer> sumArray, int runningSum) {
if (root == null){
return;
}
int newRunningSum = runningSum + root.key;
if (root.left == null && root.right == null){
sumArray.add(newRunningSum);
}
branchSumsUtil(root.left, sumArray, newRunningSum);
branchSumsUtil(root.right, sumArray, newRunningSum);
}
So I want to find the parent node of a Node in a binary tree.
Suppose that I input 30,15,17,45,69,80,7 in the tree through a text file.
The tree should be
30
15 45
7 17 69
80
And here is my code :
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
if(pRoot->pleft->value == value || pRoot->pright->value == value)
return pRoot;
if(pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
if(pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}
In this case i'm not consider if the user input the value of the Root node.
Thing is, when I input 15,17,7, all the value in the left branch of Root node, it came out ok. But when i want to find parent Node of the values from the right branch (69,80) EXCEPT for 45, the program stop running.
Any idea about what caused this error guys? Thanks for reading.
It appears that 45 does not have a left node, it is NULL, so checking pRoot->pleft->value == value is undefined behavior.
30
/ \
15 45
/ \ \
7 17 69
\
80
So you need to do a check, something like:
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
if( (pRoot->pleft != NULL && pRoot->pleft->value == value)
|| (pRoot->pright != NULL && pRoot->pright->value == value))
return pRoot;
if(pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
if(pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}
However, another thing to check for is if pRoot itself is NULL:
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if (pRoot == NULL)
return NULL;
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
if( (pRoot->pleft != NULL && pRoot->pleft->value == value)
|| (pRoot->pright != NULL && pRoot->pright->value == value))
return pRoot;
if(pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
if(pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}
Your Problem is:
if(pRoot->pleft->value == value || pRoot->pright->value == value)
because before you checked if left AND right is null. In the section mentioned above, one could be null
You maybe wanna Change your code to something like this:
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
//Added check
if(pRoot->pleft && pRoot->pleft->value == value)
return pRoot;
//Added check
if(pRoot->pright && pRoot->pright->value == value)
return pRoot;
//Check also needed here
if(pRoot->pleft && pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
//Check also needed here
if(pRoot->pright && pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}
IMHO: You could also create a pointer to the parent node in each node. This could Speed up certain things a lot!
public Node nodeParent(Node root, Node n){
if(root==null){
return null;
}
Node p=root;
if(p.left==null && p.right==null ){
return null;
}
if(p.left!=null && p.key>n.key){
p=p.left;
if(p.left.key==n.key){
return p;
}
}
if(p.right!=null && p.key<n.key){
p=p.right;
if(p.right.key==n.key){
return p;
}
}
if(p.left!=null && p.right!=null ){
if(p.key<n.key){
p=p.right;
}else{
p=p.left;
}
}
return p;
}
The following code snippet should do the trick:
public Node parent(Node root, int childValue){
if(root == null)
return null;
Node left = root.left;
Node right = root.right;
if(left != null && left.value == childValue)
return root;
else if(right != null && right.value == childValue)
return root;
else if(left != null && left.value > childValue)
return parent(left, childValue);
else if(right != null && right.value < childValue)
return parent(right, childValue);
else
return null;
}
You can also write simple iterative version of this subroutine as follows:
public Node parent(Node root, int childValue){
Node parent = NULL;
while(root != NULL && root.value != childValue) {
parent=root;
if(root.value > childValue)
root = root.left;
else
root=root.right;
}
return parent
I'm trying to make a function that tells if a Tree is "complete" or not, so basically if every subtree ends with two leaves and has no void subtrees. But when I run the code I get the following error:
[main] C:\Users\GIT\Desktop\dev\a.exe 1000 (0) handle_exceptions: Exception: STA
TUS_ACCESS_VIOLATION
[main] a 1000 (0) handle_exceptions: Dumping stack trace to a.exe.core
what should I do to solve this? Here's the code:
struct Tree {
int n;
Tree *left,*right;
Tree(): left(NULL),right(NULL) {}
};
bool isFoglia(Tree* root) {
return root->right == NULL && root->left == NULL;
}
bool isMinimum(Tree* root) {
return isFoglia(root->right) && isFoglia(root->left);
}
bool isCompleto(Tree* root) {
if(root == NULL || isFoglia(root) || isMinimum(root)) return 1;
if(isFoglia(root->right) && root->left == NULL) return 0;
if(isFoglia(root->left) && root->right == NULL) return 0;
return isCompleto(root->right) && isCompleto(root->left);
}
EDIT: I have the same error when I try to run this function that tells the maximum sum of a tree that you can get summing its elements from the top to the bottom, choosing each time which subtree to go:
int maxSum(Tree *root) {// max is an int function that returns the a if a>=b or b if b>a
if(isMinimum(root)) {
return max(root->n+root->right->n,root->n+root->left->n);
}
else {
return max(root->n+maxSum(root->right),root->n+maxSum(root->left));
}
}
Consider, for example, a tree that is severely unbalanced to the point that it is a linked list, i.e.
o
/ \
/ NULL
o
/ \
/ NULL
o
/ \
NULL NULL
And run this on the root node.
Then:
// root is not NULL, isFoglia(root) is not true, so we descend into
// isMinimum(root)
if(root == NULL || isFoglia(root) || isMinimum(root)) return 1;
whereupon in isMinimum(root),
return isFoglia(root->right) && isFoglia(root->left);
descends into isFoglia(root->right), which is isFoglia(nullptr), where finally
return root->right == NULL && root->left == NULL;
tries to take the left and right members of a null pointer.
In fact, this happens for any node that has a left child but not a right one, and further down,
if(isFoglia(root->left) && root->right == NULL) return 0;
exhibits the same problem for nodes that have a right child but not a left one. A simple fix would be to make isFoglia safely callable on null pointers, such as
bool isFoglia(Tree* root) {
return root != NULL && (root->right == NULL && root->left == NULL);
}
I'm getting a segmentation fault with my code and I'm not sure why. I'm trying to find the max value in a regular binary tree that is not ordered.
tnode<int> *maxT(tnode<int> *t)
{
if (t == NULL) return NULL;
tnode<int> *left = maxT(t->left);
tnode<int> *right = maxT(t->right);
if (left->nodeValue > right->nodeValue)
{
return maxT(left);
}
if (left->nodeValue < right->nodeValue)
{
return maxT(right);
}
}
The fundamentals of the algorithm are fairly straight forward. Because the tree is unordered, all nodes must be visited, with the following preconditions:
A null node pointer results in null as an answer.
Else a node with no children results in the current node
Else result is the max of the node compared to the max of its children.
Given that, I'm pretty sure this is what you're trying to do:
template<typename T>
tnode<T>* maxT(const tnode<T>* t)
{
if (!t)
return nullptr;
tnode<T>* lmax = maxT(t->left);
tnode<T>* rmax = maxT(t->right);
tnode<T>* cmax = (lmax && rmax)
? ((rmax->nodeValue < lmax->nodeValue ? lmax : rmax))
: (lmax ? lmax : rmax);
return (!cmax || (cmax->nodeValue < t->nodeValue) ? t : cmax);
}
tnode<int> *maxT(tnode<int> *t)
{
if (t->right == NULL && t->left == NULL) //leaf node
return t->nodeValue;
else if (t->right == NULL) //no right subtree
return MAX(t->nodeValue, maxT(t->left))
else if (t->left == NULL) //no left subtree
return MAX(t->nodeValue, maxT(t->right))
else
return MAX(maxT(t->right), maxT(t->left));
}
In your case, what happens if a node doesn't have a right or left child. Then either node->right == NULL or node->left == NULL. Yet you are trying to access left->nodeValue or right->nodeValue.
This question already has answers here:
How do you validate a binary search tree?
(33 answers)
Closed 8 years ago.
i propose a recursive implementation for checking whether binary search tree is valid:
/*
Return true if binary tree is a binary search tree
*/
bool BinaryTree::isBinarySearchTree(BinaryTree* tree, int& prev)
{
if(!isBinarySearchTree(tree->left, tree->data)) // left
return false;
if(tree->value > prev) // here
return false;
else
prev = tree->value;
return isBinaryTree(tree->right); // right
}
i have big doubt on the second check,
if(tree->value > prev) // here
return false;
whats your favorite c++ implementation for this problem?
EDIT
how would you extend to find larger BST in given tree?
It's amazing how many people get this wrong.
Here's an example of a tree which the naive solution fails to reject:
5
/ \
/ \
4 6
/ \ / \
1 7 1 7
Every invocation of a naive check will succeed, since every parent is between its children. Yet, it is clearly not a well-formed binary search tree.
Here's a quick solution:
bool test(Tree* n,
int min=std::numeric_limits<int>::min(),
int max=std::numeric_limits<int>::max()) {
return !n || (
min < n->data && n->data < max
&& test(n->left, min, n->data)
&& test(n->right, n->data, max));
}
This isn't perfect, because it requires that neither INT_MIN nor INT_MAX be present in the tree. Often, BST nodes are ordered by <= instead of <, and making that change would only reserve one value instead of two. Fixing the whole thing is left as an exercise.
Here's a demonstration of how the naive test gets it wrong:
#include <iostream>
#include <limits>
#define T new_tree
struct Tree{
Tree* left;
int data;
Tree* right;
};
Tree* T(int v) { return new Tree{0, v, 0}; }
Tree* T(Tree* l, int v, Tree* r) { return new Tree{l, v, r}; }
bool naive_test(Tree* n) {
return n == 0 || ((n->left == 0 || n->data > n->left->data)
&& (n->right == 0 || n->data < n->right->data)
&& naive_test(n->left) && naive_test(n->right));
}
bool test(Tree* n,
int min=std::numeric_limits<int>::min(),
int max=std::numeric_limits<int>::max()) {
return !n || (
min < n->data && n->data < max
&& test(n->left, min, n->data)
&& test(n->right, n->data, max));
}
const char* goodbad(bool b) { return b ? "good" : "bad"; }
int main(int argc, char**argv) {
auto t = T( T( T(1),4,T(7)), 5, T(T(1),6,T(7)));
std::cerr << "Naive test says " << goodbad(naive_test(t))
<< "; Test says " << goodbad(test(t)) << std::endl;
return 0;
}
Recursive impelentation:
bool is_bst (node *root, int min = INT_MIN, int max = INT_MAX)
{
if (root)
{
// check min/max constaint
if (root->data <= min || root->data >= max)
return false;
if (root->left != NULL)
{
// check if the left node is bigger
// or if it is not BST tree itself
if (root->data < root->left->data ||
!is_bst (root->left, min, root->data))
return false;
}
if (root->right != NULL)
{
// check if the right node is smaller
// or if it is not BST tree itself
if (root->data > root->right->data ||
!is_bst (root->right, root->data, max))
return false;
}
}
return true;
}
Iterative impelentation
node_type curr = root;
node_type prev = null;
std::stack<node_type> stack;
while (1)
{
if(curr != null)
{
stack.push (curr);
curr = curr->left;
continue;
}
if(stack.empty()) // done
return true;
curr = stack.pop ();
if (prev != null)
{
if(curr->data < prev->data)
return false;
}
prev = curr;
curr = curr->right;
}