C++ Segmentation fault BST - c++

I'm currently working on a c++ implementation of a binary search tree. Everything seems to be working perfectly, but my search function is giving me issues.
BinarySearchTree::node* BinarySearchTree::SEARCH(node* x, int key)
{
if(root == NULL) {
cout << "This is an empty tree." << endl;
return NULL;
} else {
if(x->key == key) {
return x;
}
if(x == NULL) {
cout << "Value not in tree." << endl;
return x;
}
if(key < x->key ) {
return SEARCH(x->left, key);
} else {
return SEARCH(x->right, key);
}
}
}
This gives me a segmentation fault every time I search for a key value that is not in the tree, and when the node value is NULL (such as a value that would be either the max or min if it were included).

Check NULL pointer first and then the rest. If x is NULL, accessing key by x->key will give you segmentation fault.
if(x == NULL) {
cout << "Value not in tree." << endl;
return x;
}
if(x->key == key) {
return x;
}
...

Related

Why is one of my print functions deleting nodes?

OK so I have a print function for my binary tree program that prints everything in Breadth-First. When I call it, it prints in the order that I would expect it to, however it also deletes all but ones of the nodes and leaves me with an empty tree.
void BST::breadth(Node *& cur_root)
{
if (cur_root != NULL) {
cout << cur_root->m_value;
if (cur_root->m_left != NULL) {
myqueue.push(cur_root->m_left);
}
if (cur_root->m_right != NULL) {
myqueue.push(cur_root->m_right);
}
if (!myqueue.empty()) {
cout << ", ";
cur_root = myqueue.front();
myqueue.pop();
breadth(cur_root);
} else {
cout << "}" << endl;
}
}
}
I assumed that popping the node off of myqueue might have been the problem, yet I don't have this problem when I use my normal print function (In-Order Traversal).
void BST::print(Node *& cur_root)
{
if (cur_root != NULL) {
print(cur_root->m_left);
myqueue.push(cur_root);
print(cur_root->m_right);
}
int sizecompare = myqueue.size();
if (size() == sizecompare) {
while (!myqueue.empty()) {
cout << myqueue.front()->m_value;
myqueue.pop();
if (!myqueue.empty()) {
cout << ", ";
}
}
cout << "}" << endl;
}
}
They both use the same queue of nodes, so I don't understand why they would behave differently when popped. So is the pop function the culprit? If so, why does it only happen on one function? Is there a way I can work around it so my nodes aren't destroyed?
Because you are passing cur_root by reference instead of by value. When your breadth function returns, your cur_root is pointing to something else (the end of the tree).
You can also avoid the recursion:
void BST::breadth(Node* root)
{
std::queue<Node*> myqueue;
myqueue.push_back(root);
bool first = true;
cout << "{";
while (myqueue.empty() == false) {
cout << (first ? "" : ",");
first = false;
Node* current = myqueue.front();
myqueue.pop();
cout << current->m_value;
if (current->left) {
myqueue.push(current->left);
}
if (current->right) {
myqueue.push(current->right);
}
}
cout << "}" << endl;
}
void BST::breadth(Node *& cur_root)
Takes in a reference to a pointer.
cur_root = myqueue.front();
Changes it to be one of the child nodes. You just overwrote it.

What path doesn't return the value?

I have a function to find the node in BST by its string key, using recursion.
I'm getting the warning for second function : c4715 "not all control paths return a value". I can't understand what exactly path doesn't return the value..
Here's my functions:
TreeNode* Tree::findNodeByKey(const string &str) {
if (root == NULL) {
cout << "Tree is empty, nothing found" << endl;
return nullptr;
}
else {
return findNodeByKeyHelper(root, str);
}
}
TreeNode* Tree::findNodeByKeyHelper(TreeNode *node, const string &str) {
if (node->data == str) {
cout << "node is found" << endl;
return node;
}
else if (str < node->data) {
if (node->left == nullptr) {
cout << "element was not found" << endl;
return nullptr;
}
else {
findNodeByKeyHelper(node->left, str);
}
}
else if (str > node->data) {
if (node->right == nullptr) {
cout << "element was not found" << endl;
return nullptr;
}
else {
findNodeByKeyHelper(node->right, str);
}
}
}
These paths
else if (str < node->data) {
if (node->left == nullptr) {
cout << "element was not found" << endl;
return nullptr;
}
else {
findNodeByKeyHelper(node->left, str);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
}
else if (str > node->data) {
if (node->right == nullptr) {
cout << "element was not found" << endl;
return nullptr;
}
else {
findNodeByKeyHelper(node->right, str);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
}
return nothing.
You should insert the return keyword. For example
return findNodeByKeyHelper(node->right, str);
And substitute the last else-if for else. For example
if (node->data == str) {
//...
}
else if (str < node->data) {
//...
}
else {
^^^^^^^
//...
}

Bug in AVL tree code, data structures c++

I am really trying to figure out the bug in my code I wrote for AVL tree but there seems to be a bug in it.
It calls the rotation functions but when it finishes rotation there are several problem:
root doesn't change
only root value is displayed when in-order traversal is done, other values seem to disappear
I have been trying to fix this bug since 2-3 days but cant seem to solve it.
Would love some help from you guys. I will be attaching the code with this.
/*
insertion
rotations all DONE
level order DONE
deletion
*/
#include <iostream>
#include <queue>
using namespace std;
struct node
{
int data;
int height;
node *left;
node *right;
node()
{
height = 0;
left = right = NULL;
}
};
class AVL
{
public:
node *root;
AVL()
{
root = NULL;
}
// search function
bool search(int num)
{
node *nodePtr = root;
if (root->data == num)
{
cout << "FOUND " << endl;
return true;
}
else
{
while (nodePtr != NULL)
{
if (nodePtr->data < num)
{
nodePtr = nodePtr->right;
}
else if (nodePtr->data > num)
{
nodePtr = nodePtr->left;
}
else
{
cout << "FOUND " << endl;
return true;
}
}
cout << "NOT FOUND " << endl;
return false;
}
}
// inorder
void inorder()
{
inorder(root);
}
// postorder
void postorder()
{
postorder(root);
}
// preorder
void preorder()
{
preorder(root);
}
// inorder utility function
void inorder(node *&nodePtr)
{
if (nodePtr)
{
inorder(nodePtr->left);
cout << nodePtr->data << ", ";
inorder(nodePtr->right);
}
}
// preorder utility function
void preorder(node *&nodePtr)
{
if (nodePtr)
{
cout << nodePtr->data << ", ";
preorder(nodePtr->left);
preorder(nodePtr->right);
}
}
// postorder utility function
void postorder(node *&nodePtr)
{
if (nodePtr)
{
postorder(nodePtr->left);
postorder(nodePtr->right);
cout << nodePtr->data << ", ";
}
}
// returns the number of nodes in the tree
int size(node *&nodePtr)
{
if (!nodePtr)
{
return 0;
}
else
{
return (size(nodePtr->left) + size(nodePtr->right)) + 1;
}
}
// function to check if tree is empty or not
bool isempty()
{
if (root == NULL)
{
return true;
}
else
{
return false;
}
}
// max function to calculate height and also the balance factor
int maximum(int x, int y)
{
if (x>y)
{
return x;
}
else
{
return y;
}
}
// returns the level of the tree
int returnHeight(node *&nodePtr)
{
if (nodePtr == NULL)
{
return 0;
}
else
{
return nodePtr->height;
}
}
// assigning the height to the node
void assignHeightToNode(node *&nodePtr)
{
int left = returnHeight(nodePtr->left);
int right = returnHeight(nodePtr->right);
nodePtr->height = maximum(left, right) + 1;
}
// single left rotate
node *singleLeftRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return;
// }
node * b = nodePtr->right;
nodePtr->right = b->left;
b->left = nodePtr;
return b;
}
// single right rotate
node *singleRightRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return ;
// }
node * b = nodePtr->left;
nodePtr->left = b->right;
b->right = nodePtr;
assignHeightToNode(nodePtr);
assignHeightToNode(b);
return b;
}
// double left rotate
node *doubleLeft(node *&nodePtr)
{
nodePtr->right = singleRightRotate(nodePtr->right);
return singleLeftRotate(nodePtr);
}
// double right rotate
node *doubleRight(node *&nodePtr)
{
nodePtr->left = singleLeftRotate(nodePtr->left);
return singleRightRotate(nodePtr);
}
// insert function
void insert1(int x)
{
cout << "NOW INSERTING " << x << endl;
insert2(x, root);
}
// insert utility function
void insert2(int &x, node *&nodePtr)
{
if (nodePtr == NULL)
{
node *newNode = new node;
newNode->data = x;
newNode->height = 0;
nodePtr = newNode;
checkRotations(nodePtr, x);
return;
}
else
{
if (x < nodePtr->data)
{
cout << endl << "GOING LEFT " << endl;
insert2(x, nodePtr->left);
}
else if (x > nodePtr->data)
{
cout << endl << "GOING RIGHT " << endl;
insert2(x, nodePtr->right);
}
else if (nodePtr->data == x)
{
cout << "DUPLICATE VALUES NOT ALLOWED " << endl;
return;
}
}
checkRotations(nodePtr, x);
}
// checking if rotations needed
void checkRotations(node *&nodePtr, int &x)
{
assignHeightToNode(nodePtr);
cout << endl << endl << "HEIGHT OF " << nodePtr->data << " IS " << nodePtr->height << endl;
int bf = returnHeight(nodePtr->left) - returnHeight(nodePtr->right);
cout << endl << endl << "BALANCE FACTOR AT NODE " << nodePtr->data << " IS " << bf << endl;
if (bf < -1 || bf > 1)
{
cout << endl << endl << "ROTATION IS HAPPEENING " << endl << endl;
if (x > nodePtr->data)
{
singleLeftRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE LEFT " << endl;
return;
}
else if (x < nodePtr->data)
{
singleRightRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE RIGHT " << endl;
return;
}
else if (x < root->data && x > root->left->data)
{
doubleRight(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
else if (x > root->data && x < root->right->data)
{
doubleLeft(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
}
}
// level order display code
void levelOrderDisplay()
{
levelOrderDisplay2(root);
}
// level order display utility function
void levelOrderDisplay2(node *&nodePtr)
{
if (nodePtr == NULL)
{
cout << "THE TREE IS EMPTY" << endl;
return;
}
queue <node *> displayer;
displayer.push(nodePtr);
while (!displayer.empty())
{
node *currentNode = displayer.front();
cout << currentNode->data << ", ";
if (currentNode->left != NULL)
{
displayer.push(currentNode->left);
}
else if (currentNode->right != NULL)
{
displayer.push(currentNode->right);
}
displayer.pop();
}
}
void rootD()
{
cout << "root is " << root->data << endl;
}
};
int main()
{
AVL tree;
tree.insert1(3);
tree.insert1(2);
tree.insert1(1);
tree.insert1(4);
tree.insert1(5);
tree.insert1(6);
tree.insert1(7);
tree.inorder();
// tree.rootD();
// tree.levelOrderDisplay();
// tree.rootD();
return 0;
}
I suggest you that do not pass node pointer by reference where your code does not change pointer value such as print. Try this... I completed my avl tree code just 2 3 day before and i have similar problem, when i debug my program i came to know that somehow in print function my pointer value is changed because i passed it by reference..... So.. Try this and see if work or not.... Hope this might help you.
Really late answer, but this is what you had to do. You should set the node passed in the function equal to the temporary node made in the function. In coding language, nodePtr=b should have been the last line of the single rotate functions.
Hope this helps :)

How to fix segmentation error 11 in c++

I am currently writing a binary tree project in c++ and it is giving me some errors that I am struggling to understand. The error in question is a segmentation error that I have no idea how to fix. Below is the code from one one the files where all the functions are written. The function in particular that is giving me an issue is the last one - the print_pre_order_private function.
#include <iostream>
#include <cstdlib>
#include "BT.h"
using namespace std;
BT::BT()
{
root = NULL; //makes sure pointer isn't pointing at anything
}
BT::node* BT::create_leaf(int key)
{
node* n = new node;
n->key = key;
n->left = NULL;
n->right = NULL;
return n;
}
void BT::add_leaf(int key)
{
add_leaf_private(key, root);
}
void BT::add_leaf_private(int key, node* Ptr)
{
if(root == NULL)
{
root = create_leaf(key);
}
else if(key < Ptr->key)
{
if(Ptr->left != NULL)
{
add_leaf_private(key, Ptr->left);
}
else
{
Ptr->left = create_leaf(key);
}
}
else if(key > Ptr->key)
{
if(Ptr->right != NULL)
{
add_leaf_private(key, Ptr->right);
}
else
{
Ptr->right = create_leaf(key);
}
}
else
{
cout << "The key " << key << " has already been added to the tree\n";
}
}
void BT::print_in_order()
{
print_in_order_private(root);
}
void BT::print_in_order_private(node* Ptr)
{
if(root != NULL)
{
if(Ptr->left != NULL)
{
print_in_order_private(Ptr->left);
}
cout << Ptr->key << " ";
if(Ptr->right != NULL)
{
print_in_order_private(Ptr->right);
}
}
else
{
cout << "The tree is empty\n";
}
}
BT::node* BT::return_node(int key)
{
return return_node_private(key, root);
}
BT::node* BT::return_node_private(int key, node* Ptr)
{
if(Ptr != NULL)
{
if(Ptr->key == key)
{
return Ptr;
}
else
{
if(key < Ptr->key)
{
return return_node_private(key, Ptr->left);
}
else
{
return return_node_private(key, Ptr->right);
}
}
}
else
{
return NULL;
}
}
int BT::return_root_key()
{
if(root != NULL)
{
return root->key;
}
else
{
return -1;
}
}
void BT::print_children(int key)
{
node* Ptr = return_node(key);
if(Ptr != NULL)
{
cout << "Parent Node = " << Ptr->key << endl;
Ptr->left == NULL ?
cout << "Left child = NULL\n":
cout << "Left child = " << Ptr->left->key << endl;
Ptr->right == NULL ?
cout << "Right child = NULL\n":
cout << "Right child = " << Ptr->right->key << endl;
}
else
{
cout << "Key " << key << " is not in the tree\n";
}
}
int BT::find_smallest()
{
return find_smallest_private(root);
}
int BT::find_smallest_private(node* Ptr)
{
if(root == NULL)
{
cout << "The tree is empty\n";
return -1;
}
else
{
if(Ptr->left != NULL)
{
return find_smallest_private(Ptr->left);
}
else
{
return Ptr->key;
}
}
}
void BT::remove_node(int key)
{
remove_node_private(key, root);
}
void BT::remove_node_private(int key, node* parent)
{
if(root != NULL)
{
if(root->key == key)
{
remove_root_match();
}
else
{
if(key < parent->key && parent->left != NULL)
{
parent->left->key == key ?
remove_match(parent, parent->left, true) :
remove_node_private(key, parent->left);
}
else if(key < parent->key && parent->right != NULL)
{
parent->right->key == key ?
remove_match(parent, parent->right, true) :
remove_node_private(key, parent->right);
}
else
{
cout << "The key " << key << " was not found in the tree\n";
}
}
}
else
{
cout << "The tree is empty\n";
}
}
void BT::remove_root_match()
{
if(root != NULL)
{
node* delPtr = root;
int root_key = root->key;
int smallest_right_subtree;
//case 0 - 0 children
if(root->left == NULL && root->right == NULL)
{
root = NULL;
delete delPtr;
}
//case 1 - 1 child
else if(root->left == NULL && root->right != NULL)
{
root = root->right;
delPtr->right = NULL;
delete delPtr;
cout << "The root node with key " << root_key << " was deleted. "
<< " The new root contains key " << root->key << endl;
}
else if(root->right == NULL && root->left != NULL)
{
root = root->left;
delPtr->left = NULL;
delete delPtr;
cout << "The root node with key " << root_key << " was deleted. "
<< " The new root contains key " << root->key << endl;
}
//case 2 - 2 children
else
{
smallest_right_subtree = find_smallest_private(root->right);
remove_node_private(smallest_right_subtree, root);
root->key = smallest_right_subtree;
cout << "The rout key containing key " << root_key
<< " was overwritten with key " << root->key << endl;
}
}
else
{
cout << "Cannot remove root. Tree is empty\n";
}
}
void BT::remove_match(node* parent, node* match, bool left)
{
if(root != NULL)
{
node* delPtr;
int match_key = match->key;
int smallest_right_subtree;
//case 0 - 0 children
if(match->left == NULL && match->right == NULL)
{
delPtr = match;
left == true ? parent->left = NULL : parent->right = NULL;
delete delPtr;
cout << "The node containing key " << match_key << " was removed\n";
}
//case 1 - 1 child
else if(match->left == NULL && match->right != NULL)
{
left == true ? parent->left = match->left : parent->right = match->right;
match->left = NULL;
delPtr = match;
delete delPtr;
cout << "The node containing key " << match_key << " was removed\n";
}
//case 2 - 2 children
else
{
smallest_right_subtree = find_smallest_private(match->right);
remove_node_private(smallest_right_subtree, match);
match->key = smallest_right_subtree;
}
}
else
{
cout << "Cannot remove match. The tree is empty";
}
}
void print_pre_order()
{
print_pre_order_private(root);
}
void print_pre_order_private(node* Ptr)
{
if(root != NULL)
{
cout << Ptr->key << " ";
print_pre_order_private(Ptr->left);
print_pre_order_private(Ptr->right);
}
}
Any help in fixing this situation is greatly appreciated. Thanks in advance. :)
In print_pre_order_private(node* Ptr) function. Shouldn't this be "if(Ptr != NULL)" instead of "if(root != NULL)" ?. I think there is the crash.
Since you have designed "print_pre_order_private()" function as a recursive function you should check for the validity of "Ptr" instead of always checking for the validity of "root", since the left/right/both of the child may be NULL at the very bottom of the tree depending on your input.

Printing an expression tree

I am able to print my expression tree in inorder. But I need to be able to print it in inorder with parenthesis. for example postorder 53+ should output (5+3)
I currently have:
void printTree(struct TreeNode *tree)
{
if (tree != NULL)
{
if (isalpha(tree->info) || isdigit(tree->info))
cout << "(";
printTree( tree->left);
cout<< tree->info;
printTree(tree->right);
if (isalpha(tree->info) || isdigit(tree->info))
cout << ")";
}
}
But this gives me incorrect output. If i enter postfix expression 62/5+ it gives me (6)/(2)+(5)
:(
You need to distinguish between leaf nodes and non-leaf nodes. Only non-leaf nodes are enclosed in parantheses.
bool isLeaf(struct TreeNode* tree) {
return tree->left == 0 && tree->right == 0;
}
void printTree(struct TreeNode* tree) {
if (tree != NULL) { // this test could be omitted if the printed tree is not empty
if (isLeaf(tree)) {
cout << tree->info;
}
else {
cout << "(";
printTree(tree->left);
cout << tree->info;
printTree(tree->right);
cout << ")";
}
}
}
Try reversing the if conditions that decide whether the parentheses should be printed :
void printTree(struct TreeNode *tree)
{
if (tree != NULL)
{
if (!(isalpha(tree->info) || isdigit(tree->info)))
cout << "(";
printTree( tree->left);
cout<< tree->info;
printTree(tree->right);
if (!(isalpha(tree->info) || isdigit(tree->info)))
cout << ")";
}
}
Or probably even better :
void printTree(struct TreeNode *tree)
{
if (tree != NULL)
{
if (isoperator(tree->info))
cout << "(";
printTree( tree->left);
cout<< tree->info;
printTree(tree->right);
if (isoperator(tree->info))
cout << ")";
}
}
where isoperator is appropriately defined to distinguish operators from operands.