Stack Overflow when inserting a node in a Binary Search Tree - c++

I am new to programming in C++ but I am trying to create a Binary Search Tree.
The program seems to compile fine but it gives me this error:
Unhandled exception at 0x009229B7 in Lab001_CS3.exe: 0xC00000FD: Stack
overflow (parameters: 0x00000001, 0x00AD2FBC).
when I try to run it. The error occurs on this line of code:
void insert(int value) {
...
}
I am not sure what I am doing wrong, and I have never gotten this error before.
Here is the code:
#include <iostream>
using namespace std;
//create a node struct
struct node {
//member variables
int key;
node* left;
node* right;
//default constructor
node() {
key = 0;
left = NULL;
right = NULL;
cout << "a new node is created" << endl;
}
//constructor so can create a node in one line
node(int k) {
key = k;
left = NULL;
right = NULL;
cout << "a new node is created" << endl;
}
};
class Tree {
public:
//root node
node root;
//default constructor
Tree() {
root.key = 0;
root.left = NULL;
root.right = NULL;
}
//constructor to create the root node
Tree(int data) {
//set the data to the key
//set the right and left pointers to null
root.key = data;
root.left = NULL;
root.right = NULL;
}
//print the root node
void printRootNode() {
cout << "Root Node - Key: " << root.key << endl;
}
//insert functions
void insert(int value) {
/* If the newNode's key is less than the root key, traverse left
*/
if (value < root.key) {
/* if the left node is NULL */
if (root.left == NULL) {
root.left = new node(value);
cout << "assigned left" << endl;
}
else {
/* if the left node is important */
insert(value);
cout << "recurse" << endl;
}
}
if (value > root.key) {
/* if the right node is NULL */
if (root.right == NULL) {
root.right = new node(value);
cout << "assigned right" << endl;
}
else {
/* if the right node is important */
insert(value);
cout << "recurse" << endl;
}
}
}
};
//print inorder
void inorder(node* rt) {
//base
if (rt == NULL) {
return;
}
inorder(rt->left);
cout << " " << rt->key << endl;
inorder(rt->right);
}
int main() {
//create a tree for a root node
Tree t(16);
t.printRootNode();
//create newNode
node n1(20);
node n2(31);
//insert the new nodes
t.insert(20);
t.insert(31);
//keep the window from closing
system("pause");
}
Thank you for any help.

In your insert()
if (value < root.key) {
/* if the left node is NULL */
if (root.left == NULL) {
root.left = new node(value);
cout << "assigned left" << endl;
}
else {
/* if the left node is important */
insert(value);
cout << "recurse" << endl;
}
}
let's take this go left snippet as example, if root.left != NULL the code will enter else block and recursively call insert(value) forever, which cause stack overflow, the correct operation is make current node move to root.left, and then call insert(value) recursively.
also you don't need node class at all, tree class can do all the things.
again, here is not a good place for help you debug, you need to learn how to do this yourself :-).

Related

Why original root is not changing in main function (Flatten Binary Tree to Linked List)? [duplicate]

This question already has answers here:
Function does not change passed pointer C++
(4 answers)
Closed 9 months ago.
https://leetcode.com/problems/flatten-binary-tree-to-linked-list/
i am talking about function "flatten", I know i can do it without making another function named help but I want to do this question this way. The help function is flattening the tree correctly and returning it correctly in TreeNode* ans, but it is not reflecting in root, in root it is printing from original
using namespace std;
class TreeNode {
public:
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int val) {
this->val = val;
left = right = nullptr;
}
};
TreeNode *takeInput() {
int rootData;
cout << "Enter data of root node" << endl;
cin >> rootData;
if (rootData == -1) {
return nullptr;
}
TreeNode *root = new TreeNode(rootData);
queue<TreeNode *> pendingNodes;
pendingNodes.push(root);
while (!pendingNodes.empty()) {
TreeNode *front = pendingNodes.front();
pendingNodes.pop();
int leftNodeData;
cout << "Enter val of left child of parent " << front->val << endl;
cin >> leftNodeData;
if (leftNodeData != -1) {
front->left = new TreeNode(leftNodeData);
pendingNodes.push(front->left);
}
int RightNodeData;
cout << "Enter val of Right child of parent " << front->val << endl;
cin >> RightNodeData;
if (RightNodeData != -1) {
front->right = new TreeNode(RightNodeData);
pendingNodes.push(front->right);
}
}
return root;
}
void print(TreeNode *root) {
if (root == NULL) {
return;
}
queue<TreeNode *> pendingNodes;
pendingNodes.push(root);
while (!pendingNodes.empty()) {
TreeNode *front = pendingNodes.front();
pendingNodes.pop();
cout << front->val << ":";
if (front->left != nullptr) {
cout << " L: " << front->left->val;
pendingNodes.push(front->left);
}
if (front->right != nullptr) {
cout << " R: " << front->right->val;
pendingNodes.push(front->right);
}
cout << endl;
}
}
TreeNode *help(TreeNode *root) {
if (root == nullptr) {
return nullptr;
}
TreeNode *leftAns = help(root->left);
TreeNode *rightAns = help(root->right);
if (leftAns != nullptr) {
TreeNode *temp = leftAns;
while (temp->right != nullptr) {
temp = temp->right;
}
temp->right = root;
root->left = nullptr;
}
root->right = rightAns;
if (leftAns != nullptr) {
root = leftAns;
return leftAns;
}
return root;
}
void flatten(TreeNode *root) {
TreeNode *ans = help(root);
// help(root);
// *root = *ans;
root = ans;
// root = help(root);
}
int main() {
TreeNode *root = takeInput();
print(root);
flatten(root);
cout << "ans:" << endl;
print(root);
return 0;
}```
As user207421 stated in his comment, you are currently passing root into the flatten function by value meaning that when root is assigned the value of ans in the line
root = ans;
Only the local copy of root is being altered. If you passed root into the function by reference, the value of the root value would be changed rather than just a local copy.
The function would simply need to be changed to
void flatten(TreeNode *&root) {
root = help(root);
}
Edit:
Having looked over the leet code link I now realize the previous answer is invalid for doesn't exactly match the provided flatten function signature given in the challenge. I will leave the original answer above in case it is useful. If you wish to change the value of root, you should assign the value pointed to by answer to the memory location pointed to be root
void flatten(TreeNode *root) {
*root = *help(root);
}

Strange behavior while using queue that contains pointers

I am trying to create a binary tree that when you try to add a new node to that, it adds the node to first position that is nullptr.
actually making a complete binary tree.
Look at the code below:
#include <iostream>
#include <queue>
using namespace std;
class node{
private:
char data;
node* right;
node* left;
public:
node(char n){
data = n;
left = nullptr;
right = nullptr;
}
char getdata(){
return data;
}
friend class binTree;
};
class binTree{
private:
node *root;
public:
binTree(){
root = nullptr;
}
binTree(node *root){
this->root = root;
}
node* getRoot(){
return this->root;
}
void addNode(char data){
cout << "adding " << data << endl;
if(root == nullptr) {
root = new node(data);
return;
}
queue<node*> Q;
Q.push(root);
node* toadd;
while(true) {
node* toadd = Q.front();
Q.pop();
Q.push(toadd->left);
Q.push(toadd->right);
if(toadd->left == nullptr) break;
if(toadd->right == nullptr) break;
}
if((toadd->left) == nullptr)
{
cout << "add data to the left of " << toadd -> data << endl;
toadd->left = new node(data);
} else if((toadd -> right) == nullptr){
cout << "add data to the right of " << toadd -> data << endl;
toadd->right = new node(data);
} else {
cout << "toadd left and right are not nullptr" << endl;
}
}
};
int main()
{
binTree bin;
string s = "abcdefg";
cout << s << endl << endl;
for(int i = 0; i < s.size(); i++)
{
bin.addNode(s[i]);
}
}
when I run this code the output is:
abcdefg
adding a
adding b
toadd left and right are not nullptr
adding c
toadd left and right are not nullptr
adding d
toadd left and right are not nullptr
adding e
toadd left and right are not nullptr
adding f
toadd left and right are not nullptr
adding g
toadd left and right are not nullptr
the strange part is when printing "toadd left and right are not nullptr"
because there is a while(true) and the only exit conditions are:
if(toadd->left == nullptr) break;
if(toadd->right == nullptr) break;
so one of these conditions were true that we could break the loop;
so we should enter one of if or else if part of the following code (after the while) but surprisingly we enter the else part and end of printing "toadd left and right are not nullptr".
can anyone explain this behavior?
You've defined toadd twice, once before the loop and once inside. Easy mistake to make.

Why is it that, when I try to shift all of the strings into my custom made Queue template and try to print, it only prints the last in the queue?

Truth be told, this is an assignment that I'm trying to complete. The basic thing that we have to do is create a Stack and Queue without STL and then create Stack and Queue with STL. I pretty much finished up creating my custom Stack, and it works perfectly. However, with Queue, whenever I try to shift strings into it and print it out, the console will only print out the string that was the last to be shifted. On top of that, whenever I try to unshift the last thing entered into the Queue with the code that I have, I end up getting a read access violation, that of which I am completely stumped on resolving.
If you don't mind, can you look through my code and help me understand what I did that is causing this error and the last entry in my Queue to be the only one printed out? Thanks in advance.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct Node {
//create a node struct
string data;
Node *next;
};
class Stack {
public:
Stack();
~Stack();
void push(string a);
string pop();
string toString();
bool isEmpty();
private:
Node * top;
};
class Queue {
public:
Queue();
~Queue();
void shift(string a);
string unshift();
string toString();
bool isEmpty();
private:
Node * top;
Node * bottom;
int count;
};
Stack::Stack() {
//initializes stack to be empty
top = NULL;
}
Queue::Queue() {
//initializes stack to be empty
top = NULL;
}
Stack::~Stack() {
//deconstructor to delete all of the dynamic variable
if (top == NULL) {
cout << "Nothing to clean up" << endl;
}
else {
cout << "Should be deleting..." << endl;
}
}
Queue::~Queue() {
//deconstructor to delete all of the dynamic variable
if (bottom == NULL) {
cout << "Nothing to clean up" << endl;
}
else {
cout << "Should be deleting..." << endl;
}
}
void Stack::push(string a) {
//Need a new node to store d in
Node *temp = new Node;
temp->data = a;
temp->next = top;//point the new node's next to the old top of the stack
top = temp;//point top to the new top of the stack
}
void Queue::shift(string a) {
//Need a new node to store d in
Node *temp = new Node;
temp->data = a;
temp->next = NULL;//point the new node's next to the old top of the stack
if (isEmpty()) {
top = temp;
}
else {
top->next = temp;
count++;
}
top = temp;//point top to the new top of the stack
}
string Stack::pop() {
if (!isEmpty()) {
string value = top->data;
Node *oldtop = top;
top = oldtop->next;
delete oldtop;
return value;
}
else {
cout << "You can't pop from an empty stack!" << endl;
exit(1);
}
}
string Queue::unshift() {
if (isEmpty()) {
cout << "You can't unshift an empty Queue!" << endl;
exit(1);
}
else{
Node *oldbot = top;
if (top == bottom) {
top = NULL;
bottom = NULL;
}
else {
string value = top->data;
}
delete oldbot;
count--;
}
}
string Stack::toString() {
string result = "top ->";
if (isEmpty()) {
result = result + "NULL";
return result;
}
else {
Node *current = top;
while (current != NULL) {
result = result + current->data + "->";
current = current->next;
}
result = result + "(END)";
return result;
}
}
string Queue::toString() {
string result = "top ->";
if (isEmpty()) {
result = result + "NULL";
return result;
}
else {
Node *current =top;
while (current != NULL) {
result = result + current->data + "->";
current = current->next;
}
result = result + "(END)";
return result;
}
}
bool Stack::isEmpty() {
return(top == NULL);
}
bool Queue::isEmpty() {
return(top == NULL);
}
int main()
{
Stack *s = new Stack();
cout << "Output when empty: " << endl << s->toString() << endl;
s->push("Cheeseburger");
s->push("Pizza");
s->push("Large coffee");
s->pop();
cout << "Output when not empty: " << endl << s->toString() << endl;
delete s;
cin.get();
Queue *b = new Queue();
cout << "Output when empty: " << endl << b->toString() << endl;
b->shift("Cheeseburger");
b->shift("Pizza");
b->shift("Large coffee");
cout << "Output when not empty: " << endl << b->toString() << endl;
b->unshift();
delete b;
cin.get();
}
You have to comment below statement in Queue::shift method -
top = temp;

Find parent node function for binary tree

is it possible to write a function to return the parent node of a given node for a binary tree?
BinaryTree *search_val(BinaryTree *bt, int val)
{
//temp pointer
BinaryTree* temp = NULL;
if(!bt->isEmpty())
{
//check if root is equal to value and return root if true
if(bt->getData() == val)
{
return bt;
}
else
{
//search left side
temp = search_val(bt->left(), val);
//if not found in left, search right
if (temp == NULL)
{
temp = search_val(bt->right(), val);
}
return temp;
}
return NULL;
}
return NULL;
}
I just have this search function at the moment. I got it from here actually. So I'm trying to convert this to search for the parent of a node. The parameters will be the root node and the node whose parent we want. Is that even possible?
I just need some hints to get started then I'll post my code. The purpose of creating this function is because I have a delete leaf node function that works almost perfectly....the only problem is that when I print all nodes after deleting, the supposedly deleted node still appears. I'm sure it's because the parent node is still linked to it in main. Here's my delete leaf node function:
void delete_leaf_node(BinaryTree *bt, int val)
{
BinaryTree *temp;
temp = search_val(bt, val);
//If node does not exist in the tree, inform the user
if(temp == NULL)
{
cout << "\n " << val << " was not found in the tree" << endl;
}
//Check if node is a leaf
else if(temp->isLeaf())
{
delete temp;
cout << "\n Leaf " << temp->getData() << " deleted" << endl;
}
//Inform user that node is not a leaf
else
cout << "\n " << temp->getData() << " is not a Leaf" << endl;
//Display using In Order Traversal to see that the node was actually deleted
cout << "\n In Order Traversal after deleting: " << endl << "\n ";
inOrderTraverse(bt);
cout << endl;
}
I hope I'm making sense to someone...sorry I tried to shorten the question but couldn't.
BinaryTree.h file:
using namespace std;
//BinaryTree class
class BinaryTree{
public:
BinaryTree();
bool isEmpty();
bool isLeaf();
int getData();
void insert(const int &DATA);
BinaryTree *left();
BinaryTree *right();
void makeLeft(BinaryTree *bt);
void makeRight(BinaryTree *bt);
private:
bool nullTree;
int treeData;
BinaryTree *leftTree;
BinaryTree *rightTree;
};
BinaryTree.cpp file:
#include <iostream>
#include "BinaryTree.h"
using namespace std;
//constructor
BinaryTree::BinaryTree()
{
nullTree = true;
leftTree = NULL;
rightTree = NULL;
}
/*
is_empty function for BinaryTree class. Does not take any parameters.
Returns true if tree is empty and false otherwise.
*/
bool BinaryTree::isEmpty()
{
return nullTree;
}
/*
is_leaf function for BinaryTree class. Does not take any parameters.
Returns true if node has no children and false otherwise.
*/
bool BinaryTree::isLeaf()
{
return ((this->leftTree->treeData == 0) && (this->rightTree->treeData == 0));
}
/*
getData function for BinaryTree class. Does not take any parameters.
Returns treeData value.
*/
int BinaryTree::getData()
{
if(!isEmpty());
return treeData;
}
/*
insert function for BinaryTree class. Takes one parameter, passed by
reference. Returns true if node has no children and false otherwise.
*/
void BinaryTree::insert(const int &DATA)
{
//create empty children and insert DATA
treeData = DATA;
if(nullTree)
{
nullTree = false;
leftTree = new BinaryTree;
rightTree = new BinaryTree;
}
}
/*
left function for BinaryTree class. It points to the left node.
Does not take any parameters. Returns left node.
*/
BinaryTree *BinaryTree::left()
{
if(!isEmpty());
return leftTree;
}
/*
right function for BinaryTree class. It points to the right node.
Does not take any parameters. Returns right node.
*/
BinaryTree *BinaryTree::right()
{
if(!isEmpty());
return rightTree;
}
/*
makeLeft function for BinaryTree class. Takes a pointer to a tree node as a parameter.
makes the parameter the left child of a node. Does not return any value
*/
void BinaryTree::makeLeft(BinaryTree *bt)
{
if(!isEmpty());
leftTree = bt;
}
/*
makeRight function for BinaryTree class. Takes a pointer to a tree node as a parameter.
makes the parameter the right child of a node. Does not return any value
*/
void BinaryTree::makeRight(BinaryTree *bt)
{
if (!isEmpty());
rightTree = bt;
}
Thanks
That depends on your BinaryTree implementation. As far as I see, if you don't save a reference inside each node to his parent, you can't directly access to it when deleting
Edit
You can modify your BinaryTree class with:
class BinaryTree{
public:
BinaryTree();
bool isEmpty();
bool isLeaf();
int getData();
void insert(const int &DATA);
BinaryTree *left();
BinaryTree *right();
void makeLeft(BinaryTree *bt);
void makeRight(BinaryTree *bt);
void setParent(BinaryTree *parent);
BinaryTree* getParent();
private:
bool nullTree;
int treeData;
BinaryTree *leftTree;
BinaryTree *rightTree;
BinaryTree* parent;
};
Then in your .cpp:
BinaryTree::BinaryTree()
{
nullTree = true;
leftTree = NULL;
rightTree = NULL;
parent = NULL;
}
void BinaryTree::setParent(BinaryTree *parent){
this->parent = parent;
}
BinaryTree* BinaryTree::getParent(){
return parent;
}
Your delete function will look like:
void delete_leaf_node(BinaryTree *bt, int val)
{
BinaryTree *temp;
temp = search_val(bt, val);
//If node does not exist in the tree, inform the user
if(temp == NULL)
{
cout << "\n " << val << " was not found in the tree" << endl;
}
//Check if node is a leaf
else if(temp->isLeaf())
{
// You must distinguish which child you are
BinaryTree* parent = temp->getParent();
BinaryTree* leftChild = parent->left;
BinaryTree* rightChild = parent->right;
if(leftChild == temp){
parent->left = null;
}
if(rightChild == temp){
parent->right = null;
}
delete temp;
cout << "\n Leaf " << temp->getData() << " deleted" << endl;
}
//Inform user that node is not a leaf
else
cout << "\n " << temp->getData() << " is not a Leaf" << endl;
//Display using In Order Traversal to see that the node was actually deleted
cout << "\n In Order Traversal after deleting: " << endl << "\n ";
inOrderTraverse(bt);
cout << endl;
}

Segmentation Fault (core dumped) when trying to run Queue program - C++

I keep getting a Segmentation fault (core dumped) error every time I try to run my code with g++ on Linux. It compiles fine, but then that happens ... All the functions (remove, add and print) seem to have the same problem, I can't seem to figure out what's wrong... Please heeeelppp.
#include <iostream>
#include <string>
using namespace std;
//Create a node struct
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
//set to NULL
Queue::Queue() {
head = tail = NULL;
size = 0;
}
//destructor
//call remove until empty
Queue::~Queue() {
while (!isEmpty())
remove();
}
//adds a node with the given data at the back of the queue
void Queue::add(int d) {
Node *temp = new Node();
temp->data = d;
temp->next = NULL;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
//removes the node at the head of the queue and returns its data
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *temp = new Node;
temp = head;
int value = head->data;
//moves pointer to next node
head = head->next;
cout << "Removed: " << head->data << endl;
size--;
delete temp;
return value;
}
}
//determines if the queue is empty
bool Queue::isEmpty() {
return (size == 0);
}
//prints the contents of the queue from front to back, or front
//to back, depending on the value of the parameter
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p = new Node;
if (o == true) {
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
p = head;
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
p = tail;
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(8);
return 0;
}
EDIT: I've made some changes to the code... But I'm still getting the same error. I assume I'm not updating the head and the tail and/or the next and prev nodes correctly... I don't know why it's wrong or what I'm missing, though.
#include <iostream>
#include <string>
using namespace std;
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
Queue::Queue() {
head = tail = NULL;
size = 0;
}
Queue::~Queue() {
while (!isEmpty())
remove();
}
void Queue::add(int d) {
Node *temp = new Node;
temp->data = d;
temp->next = NULL;
temp->prev = tail;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
return 0;
} else {
Node *temp = head;
int value = head->data;
cout << "Removed: " << head->data << endl;
//moves pointer to next node
head = head->next;
head->prev = NULL;
size--;
delete temp;
return value;
}
}
bool Queue::isEmpty() {
return (size == 0);
}
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p;
if (o == true) {
p = head;
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
p = tail;
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(9);
q.add(10);
q.add(11);
q.add(12);
q.add(13);
q.add(14);
q.add(15);
q.add(16);
q.remove();
q.remove();
q.printQueue(true);
q.printQueue(false);
return 0;
}
Lots of problems:
You have a double-linked Node but never update its prev member in the add/remove methods.
You are keeping track of both the Queue head/tail but don't properly update them when you add/remove nodes.
Both your forward and reverse loops in printQueue() are wrong and result in an infinite loop for any queue with 2 or more elements. Queue output should be just something like:
Node *p = head;
while (p != NULL)
{
cout << p->data << " ";
p = p->next;
}
Possible null pointer deference in remove() at cout << "Removed: " << head->data << endl; since you've already moved the head pointer by this time. Move the head after the cout.
Memory leak in Queue::remove() at Node *temp = new Node;. Just do Node* temp = head;.
Memory leak in Queue::printQueue() at Node *p = new Node;. You don't need to allocate a node here.
No return value in remove() for an empty queue.
Edit
Don't forget to initialize the tail when adding a node to an empty list:
if (isEmpty()) {
head = temp;
tail = temp;
}
To remove a node from the head of a non-empty list it should be something like:
Node *temp = head;
head = head->next;
if (head) head->prev = NULL;
size--;
delete temp;
if (isEmpty()) tail = NULL;