Why does this code fragment giving me a segmentation fault? - c++

I am writing a binary search tree and this function called Search takes a value x and searches the nodes in the tree and returns whether it is a leaf or not.
bool search(Node<T>* &currentNode, const T& x) const
{
//~ cout << "CURRENT NODE DATA: " << currentNode->data << " : ";
/* FUNCTION: Searches for variable that is passed in X and checks if this value is a leaf or not */
//Left Subtree Search
if (x < binTree<T>::root->data)
{
if ((leaf(currentNode)) == true)
{
return true;
}
else
{
search(currentNode->left, x);
}
}
//Right Subtree Search
else if (x >= binTree<T>::root->data)
{
//If node in right subtree is a node check
if ((leaf(currentNode)) == true)
{
return true;
}
else
{
search(currentNode->right, x);
}
}
//Return false if the node is not a leaf
return false;
} //END OF SEARCH FUNCTION
bool leaf(Node<T>* currentNode) const
{
return ((currentNode->left == nullptr && currentNode->right == nullptr) ? true : false);
}
The seg fault occurs when I recursively call the search function with new updated node. The binary tree is initialized with 100 values and it starts searching at the root.

This code
if (x < binTree<T>::root->data)
is checking against root, note currentNode, so the test will never change. So if your x value is less than root->data you will keep trying to recurse through currentNode->left until you either hit a leaf (if you are lucky) or you hit a node with a NULL left pointer, in which case you will recurse with currentNode as NULL, which will cause a segfault in leaf when it tries to check for currentNode->left
You should be checking against currentNode. You should also be returning the return value of your search recursive calls

You have to declare
bool leaf(Node<T>* currentNode) const
BEFORE search
Easy fix, copy and paste bool leaf(Node<T>* currentNode) const; before your search function

Related

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.

Sum of Each Branch in a Binary Search Tree

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);
}

BST method returns Segfault

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.

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.

How to find the leaf of a binary tree?

I am writing a binary tree with a search function. The function is supposed to take an argument x which denotes the value to be searched and once it is found, determine if it is a leaf or not. If the value is not found, the search functions returns false.
Here is what I have which gives me a seg fault and has been just giving me false returns for every value from 1 to 100. The binary tree is initalized with 100 values.
bool search(Node<T>* &currentNode, const T& x) const
{
//~ cout << "CURRENT NODE DATA: " << currentNode->data << " : ";
/* FUNCTION: Searches for variable that is passed in X and checks if this value is a leaf or not */
//Left Subtree Search
if (x < currentNode->data)
{
if ((leaf(currentNode)) == true)
{
return true;
}
else
{
search(currentNode->left, x);
}
}
//Right Subtree Search
else if (x >= currentNode->data)
{
//If node in right subtree is a node check
if ((leaf(currentNode)) == true)
{
return true;
}
else
{
search(currentNode->right, x);
}
}
//Return false if the node is not a leaf
return false;
} //END OF SEARCH FUNCTION
void remove(Node<T>* &currentNode, const T& x)
{
}
bool leaf(Node<T>* currentNode) const
{
if (currentNode != nullptr)
{
return ((currentNode->left == nullptr && currentNode->right == nullptr) ? true : false);
}
else
{
return true;
}
}
Additionally, the leaf function returns true when currentNode is nullptr, assuming the check for nullptr in search is resolved. Is this the behavior you want for a pointer pointing to a non-existent leaf?
In your search function, you recourse on the child nodes without seeing if they're nullptr first... Then you try to de reference the data element still without checking for null.