Why is this C++ code producing a segmentation fault? - c++

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.

Related

access to an object member passed by unique_ptr

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

Recursive Function Error: "-var-create: unable to create variable object"

I made a Binary Tree for storing 2 chars 'R' and 'B'. The inserting and printing functions work fine but while executing searching function, the pointer variable gives the error -var-create: unable to create variable object when watched under VS code's debugger tool.
Node Struct Code:
struct Node
{
Node * left;
Node * right;
char value;
bool endSeq = false;
};
BST's Search Functions:
bool search(string k)
{
int len = k.length();
bool found = false;
searchHelper(root, k, len, found);
if(found)
{
return true;
}
return false;
}
Node * searchHelper(Node * p, string k, int & len, bool & found)
{
if(p == NULL)
{
return NULL;
}
else if(len == 0)
{
if(p->endSeq)
{
found = true;
}
return p;
}
else if(k[0] < p->value || (k[0] == 'B' && k[0] == p->value))
{
string kNew = k.substr(1, --len);
if(p->endSeq)
{
found = true;
}
else
{
insertHelper(p->left, kNew, len);
}
}
else if(k[0] > p->value || (k[0] == 'R' && k[0] == p->value))
{
string kNew = k.substr(1, --len);
if(p->endSeq)
{
found = true;
}
else
{
insertHelper(p->right, kNew, len);
}
}
return p;
}
Theres a problem in your code. You have made a wrong recursive call. Instead of calling insertHelper you should call searchHelper

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum

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

Add-Leaf function "hanging", custom BST Class in C++

This problem is a little more complicated than previous ones I've brought here, so I'll try to be very explicit about what I've narrowed it down to.
I'm writing a Binary Search Tree data class in C++ that functions like a standard BST except that it stores duplicates of Odd numbers using a "count" field in the BST node.
I've written a test driver to test the member functions of the class and have run into an error that I cannot seem to solve. When I attempt to add a set number of random integers to a BST object none of them seem to make it into the tree. To check the contents I use a printInOrder function that I have confirmed works properly so I know the problem isn't there.
For starters, I'll post the addLeaf, printInOrder, and createLeaf functions, and the small block of code where I call them in my driver file.
bool fixedDupBST::addLeaf(int key)
{
if(root == nullptr){
root = createLeaf(key);
assert(root != nullptr);
}
else {
node *prev = nullptr;
node *scanPtr = root;
bool right, dupe = false;
while(scanPtr != nullptr) {
prev = scanPtr;
if(key < scanPtr->key) {
scanPtr = scanPtr->left;
right = false;
}
else if (key == scanPtr->key) {
if (scanPtr->keyCount >= 1)
dupe = true;
else{
dupe = false;
scanPtr = nullptr;
}
}
else {
scanPtr = scanPtr->right;
right = true;
}
}
if (dupe)
prev->keyCount++;
else if (!dupe)
return false;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
}
return true;
}
fixedDupBST::node* fixedDupBST::createLeaf(int key)
{
node* newNode = new node;
assert(newNode != nullptr);
newNode->key = key;
newNode->left = nullptr;
newNode->right = nullptr;
if (key % 2 != 0)
newNode->keyCount = 1;
else
newNode->keyCount = 0;
return newNode;
}
void fixedDupBST::printInOrder()
{
printInOrderPr(root);
}
void fixedDupBST::printInOrderPr(node* Ptr)
{
if(root != nullptr) {
if(Ptr->left != nullptr){
printInOrderPr(Ptr->left);
}
cout << Ptr->key << ' ';
if(Ptr->right != nullptr) {
printInOrderPr(Ptr->right);
}
}
else {
cout << "The tree is empty" << endl;
}
return;
}
void testInsert(fixedDupBST &BST)
{
int temp;
for (int i = 0; i < TEST_PARAM; i++) {
temp = randNum();
BST.addLeaf(temp);
}
BST.printInOrder();
return;
}
The problem I'm getting is that when I call printInOrder() it always gives "The tree is empty". At first I thought it might be a problem with how I was passing parameters in the class member functions (pass by references vs pass by value) but that didn't provide any solutions. If there are any problems at all with the rest of the function it doesn't seem to matter because root never gets assigned to that first node, (hence why print in order just says "the tree is empty".
I need a second set of eyes on this; thanks in advanced for you help, and let me know if I can rephrase my question or provide more information to help make the situation clearer.
EDIT: R Sahu had the error correct, but his answer is a little off. I realized that a bool wouldn't work cleanly for what I was trying to do because there are actually 3 cases:
The number is a duplicate and is odd,
the number is a duplicate and is even
and the number is NOT a duplicate.
The problem stemmed from the fact that the quit condition for the while loop was scanPtr being null, and the if/else-if statement at the end had no way of knowing if it was null because it reached the end of a subtree and was ready to insert, or if I had manually set it to null upon finding a duplicate in order to break the loop appropriately.
Here is the solution I came up with.
bool fixedDupBST::addLeaf(int key)
{
if(root == nullptr){
root = createLeaf(key);
assert(root != nullptr);
}
else {
node *prev = nullptr;
node *scanPtr = root;
bool right;
int dupe = 0; // switch variable
while(scanPtr != nullptr) {
prev = scanPtr;
if(key < scanPtr->key) {
scanPtr = scanPtr->left;
right = false;
}
else if (key == scanPtr->key) {
if (key % 2 != 0) {
dupe = 1;
scanPtr = nullptr;
}
else{
dupe = 2;
scanPtr = nullptr;
}
}
else {
scanPtr = scanPtr->right;
right = true;
}
}
if (dupe == 2)
return false;
if (dupe == 1)
prev->keyCount++;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
}
return true;
}
Everything works appropriately now.
You have a logic error in this block.
if (dupe)
prev->keyCount++;
else if (!dupe) // This is pointless
// dupe is either true or false.
// Your code will never get to the next "else if"
return false;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
What you need is:
if (dupe) {
prev->keyCount++;
return false; // I think you want to return false here but I am not sure
}
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
R Sahu had the error correct, but his answer is a little off. I realized that a bool wouldn't work cleanly for what I was trying to do because there are actually 3 cases:
1: The number is a duplicate and is odd.
2: the number is a duplicate and is even.
3: the number is NOT a duplicate.
The problem stemmed from the fact that the quit condition for the while loop was scanPtr being null, and the if/else-if statement at the end had no way of knowing if it was null because it reached the end of a subtree and was ready to insert, or if I had manually set it to null upon finding a duplicate in order to break the loop appropriately.
Here is the solution I came up with.
bool fixedDupBST::addLeaf(int key)
{
if(root == nullptr){
root = createLeaf(key);
assert(root != nullptr);
}
else {
node *prev = nullptr;
node *scanPtr = root;
bool right;
int dupe = 0; // switch variable
while(scanPtr != nullptr) {
prev = scanPtr;
if(key < scanPtr->key) {
scanPtr = scanPtr->left;
right = false;
}
else if (key == scanPtr->key) {
if (key % 2 != 0) {
dupe = 1;
scanPtr = nullptr;
}
else{
dupe = 2;
scanPtr = nullptr;
}
}
else {
scanPtr = scanPtr->right;
right = true;
}
}
if (dupe == 2)
return false;
if (dupe == 1)
prev->keyCount++;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
}
return true;
}
Everything works appropriately now.

Access violation reading location 0x00000000 in binary search tree

Just showing how the node of the binary tree looks like. I'm not sure what is wrong but I have a feeling it has something to do with the function being private. How I can compare the private data so I can see if the value I am looking for is inside that node?
class binarytree
{
private:
class node
{
public:
int data;
node * left;
node * right;
node (int x)
{
data = x;
left=NULL;
right=NULL;
}
};
node * root;
This is how I insert the node
void insert(int x, node * &r)
{
if(r==NULL)
{
r= new node(x);
}
else
{
if(x < r->data)
{
//insert left
insert(x, r->left);
}
else
{
//insert right
insert(x, r->right);
}
}
}
Here is the part of the code that gives me trouble when I try to compare x to r->data the program crashes and gives me the error message " Access violation reading location 0x00000000"
void remove(int x, node * &r)
{
if(x == r->data)
{
if(r->right == NULL && r->left == NULL)
{
r = NULL;
}
else if(r->right == NULL && r->left != NULL)
{
r = r->left;
}
else if(r->right != NULL && r->left == NULL)
{
r = r->right;
}
else
{
node * temp;
temp =r;
r = r->left;
while(r->right != NULL)
{
r = r->right;
}
r->right = temp->right;
delete temp;
}
}
else if ( x < r->data)
{
remove(x, r->left);
}
else if (x > r->data)
{
remove(x , r->left);
}
}
This is where the functions are publicly. Then I call the private functions so I can manipulate the private tree.
public:
binarytree()
{
root = NULL;
}
~binarytree()
{
//tooo: write this
}
//return true if empty, false if not
bool empty()
{}
void insert(int x)
{
insert(x, root);
}
void remove(int x)
{
remove(x,root);
}
};
EDIT: Here is another function of the program that works but might be causing r to point to NULL.
int extractMin(node * &r)
{
if(r->left == NULL)
{
if(r->right == NULL)
{
return r->data;
}
else
{
int x = r->data;
r = r->right;
return x;
}
}
else
{
return extractMin(r->left);
}
}
Here is the new function to check to see if r is NULL
void remove(int x, node * &r)
{
if(r == NULL)
{
cout<<"why am I null?"<<endl;
}
else
{
if(x == r->data)
{
if(r->right == NULL && r->left == NULL)
{
r = NULL;
}
else if(r->right == NULL && r->left != NULL)
{
r = r->left;
}
else if(r->right != NULL && r->left == NULL)
{
r = r->right;
}
else
{
node * temp;
temp =r;
r = r->left;
while(r->right != NULL)
{
r = r->right;
}
r->right = temp->right;
delete temp;
}
}
else if ( x < r->data)
{
remove(x, r->left);
}
else if (x > r->data)
{
remove(x , r->left);
}
}
}
you should always check for NULL before trying to get to the inner members:
void remove(int x, node * &r)
{
if(r != NULL)
{
// Your code
}
}
you call to remove with r as NULL and then try to check r.Left. then here you have access violation
also i must ask, did any if this worked for you? specifically insert wont work this way.
try
void insert(int x, node * &r)
{
if(r==NULL)
{
r= new node(x);
}
else
{
if(x < r->data)
{
if(r->left != NULL)
{
//insert left
insert(x, r->left);
}
else
{
r->left = new node(x);
}
}
else
{
if(r->right != NULL)
{
//insert right
insert(x, r->right);
}
else
{
r->left = new node(x);
}
}
}
}
r is null somehow. You need to check if the r passed in is NULL, or check if the root is non-null, and call remove on children only if they exist.
Well it the error says, r is pointing to NULL when you try to derefference it.
So you have to make sure when you assign memmory to r it doesn't return NULL.
binarytree()
{
root = NULL;
}
void remove(int x)
{
remove(x,root);
}
In your case you are trying to derefference NULL (as the error says) This happens in your code when you are calling a remove before you have called an insert.
You simply should check at the beginning of remove for r isn't pointing to NULL.
Or even better, make sure you won't parse in r when its NULL.
You are comparing x to the root. When your tree is empty, root == nullptr. You should check to see if r == nullptr first, as in:
bool remove(int x, node * &r) {
if(!r) {
return false; // Indicate whether removal succeeded
}
//... etc.
}