Binary Tree In Order Traversal causing Stack Overflow - c++

Ok so, I have a read method that is reading the values in correctly (all 7000), (hand written 15 values as a tree structure), doesn't create any errors.
However, when it comes to the output of the binary tree I am using the method as stated on several websites.
The error I am getting is a stack overflow, and I am assuming its due to the recursive calls and never breaking out, But I have no idea why this isn't working.
Any help is appreciated, thanks.
Code Listed Below:
// Read
void BinaryTreeStorage::read(ifstream& _fin)
{
// Get first line with number of names in it
string numberOfNamesString;
getline(_fin, numberOfNamesString);
// Loop through all the names
string line;
int num = 0;
while (!_fin.eof())
{
getline(_fin, line);
if (line != "")
{
// Insert Value Here
if (root != NULL)
{
insert(line, root);
}
else
{
insert(line);
}
}
}
}
// Write
void BinaryTreeStorage::write(ofstream& _out) const
{
inorderPrint(_out, root);
}
// inorderPrint
void BinaryTreeStorage::inorderPrint(ofstream& _out, node *_root) const
{
if (_root != NULL)
{
// Inorder
inorderPrint(_out, root->left);
_out << root->nodeValue;
cout << root->nodeValue << " ";
inorderPrint(_out, root->right);
}
}
// Insert if root is null
void BinaryTreeStorage::insert(string _nodeValueIn)
{
if(root!=NULL)
insert(_nodeValueIn, root);
else
{
root=new node;
root->nodeValue=_nodeValueIn;
root->left=NULL;
root->right=NULL;
}
}
// Insert when root is not null
void BinaryTreeStorage::insert(string _nodeValueIn, node *leaf)
{
if(_nodeValueIn< leaf->nodeValue)
{
if(leaf->left!=NULL)
insert(_nodeValueIn, leaf->left);
else
{
leaf->left=new node;
leaf->left->nodeValue=_nodeValueIn;
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
}
}
else if(_nodeValueIn>=leaf->nodeValue)
{
if(leaf->right!=NULL)
insert(_nodeValueIn, leaf->right);
else
{
leaf->right=new node;
leaf->right->nodeValue=_nodeValueIn;
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
}
}
}

You have a bug in BinaryTreeStorage::inorderPrint,
your param _root is not used where intended: You always loop on root instead.
hint: Avoid using similar names!
hint: Avoid using std to avoid bugs, unless you write std:: too often in nested templates.
hint: Do not use _ at the beginning or end of names.
hint: Do not compare with NULL: Write if(n) instead of if(n!=NULL).
hint: Do not nest blocks when not needed:
void BinaryTreeStorage::inorderPrint(std::ofstream& out, node *n) const
{
if(!n) return;
inorderPrint(out, n->left);
out << n->nodeValue; // no separator??
std::cout << n->nodeValue << " ";
inorderPrint(out, n->right);
}

void BinaryTreeStorage::inorderPrint(ofstream& _out, node *_root) const
{
if (_root != NULL)
{
// Inorder
inorderPrint(_out, root->left);
In the above code, I can see _root defined but you're using root in your call (last line above). I think that is causing the infinite loop.

When you constructed your tree nodes did you ensure that the left and right pointers are initialized to NULL?

The depth of the call tree of inorderPrint is the same as the depth of the tree itself. It looks like you don't try to keep the tree balanced, so the depth can get as large as the size of the tree.
There are a few ways of fixing this. You can make sure that the tree always remains balanced so that the depth grows logarithmically with the size of the tree. Or you can make the tree threaded, which lets you visit the nodes iteratively.

Related

Binary Tree - Print Left branches only - Using PostOrder Traverse - C++

Hi!
I would like to know what can be the if statement's condition so all left branches of a binary tree could be printed using postorder traverse.
template <class dataType>
void PrintLeft (BinaryTree <dataType> * bt) {
if (!(bt == NULL))
{
//traverse left child
PrintLeft (bt->left());
//traverse right child
PrintLeft (bt->right());
//visit tree
if(/*no idea what goes here*/)
cout << bt->getData() <<"\t";
}
}
I understand that you want to visit only the nodes that were seen from a left branch. Since it is postorder, you must visit them when you get back on the right branch. So, such as said by πάντα ῥεῖ, you can use a boolean flag indicating from which type of branch you have discovered the node.
So a possible way would be as follows:
using Node = BinaryTree <int>; // or another type supporting << operator
void printLeft(Node * root, bool from_left)
{
if (root == nullptr) // empty tree?
return;
printLeft(root->left, true); // this node must be visited in postorder
printLeft(root->right, false); // this one must not be visited in postorder
if (from_left) // was root seen from a left arc?
cout << root->getData() << "\t"; // visit only if was seen from a left branch
}
There is an ambiguity with the root. I assume that it must not be printed because it is not reached from a left branch (nor right too).
So the first call should be:
printLeft(root, false);
Just as verification, for this tree:
The algorithm produces as left postorder traversal the following sequence
0 1 4 3 8 9 12 11 16 18
here goes code for postorder traversing
void postorder(BinaryTree *bt)
{
if(bt!=NULL)
{
postorder(t->lp);
postorder(t->rp);
//No Code Goes Here
cout<<bt->data<<"\t";
}
}
Try This One
void leftViewUtil(struct node *root, int level, int *max_level)
{
// Base Case
if (root==NULL) return;
// If this is the first node of its level
if (*max_level < level)
{
printf("%d\t", root->data);
*max_level = level;
}
// Recur for left and right subtrees
leftViewUtil(root->left, level+1, max_level);
leftViewUtil(root->right, level+1, max_level);
}
// A wrapper over leftViewUtil()
void leftView(struct node *root)
{
int max_level = 0;
leftViewUtil(root, 1, &max_level);
}
// Driver Program to test above functions
int main()
{
struct node *root = newNode(12);
root->left = newNode(10);
root->right = newNode(30);
root->right->left = newNode(25);
root->right->right = newNode(40);
leftView(root);
return 0;
}
if(!bt->left()==NULL)
cout << bt->left()->getData() << "\t";

C++ - Min heap implementation and post order traversal

So I have this small program that creates a min heap and insert values based on user input. If the users says change value 10 to 20, the program should change all occurrences of 10 to 20 and then heapify. When the user gives the print command the program should traverse the tree in postorder and print all the values. So I have written program but its giving me the incorrect output when I print. What am I doing wrong here:
int pArray[500];
int i = 0;
//Definition of Node for tree
struct TNode {
int data;
TNode* left;
TNode* right;
};
void Heapify(TNode* root, TNode* child);
// Function to create a new Node in heap
TNode* GetNewNode(int data) {
TNode* newNode = new TNode();
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
// To insert data in the tree, returns address of root node
TNode* Insert(TNode* root,int data) {
if(root == NULL) { // empty tree
root = GetNewNode(data);
}
// if the left child is empty fill that in
else if(root->left == NULL) {
root->left = Insert(root->left,data);
}
// else, insert in right subtree.
else if(root->right == NULL){
root->right = Insert(root->right,data);
}
else {
root->left = Insert(root->left,data);
}
Heapify(root, root->left);
Heapify(root, root->right);
return root;
}
void Heapify(TNode* root, TNode* child){
if(root != NULL && child != NULL){
if(root->data > child->data){
int temp = child->data;
child->data = root->data;
root->data = temp;
}
}
}
void Change(TNode* root,int from, int to) {
if (root == NULL)
return;
else if (root->data == from)
root->data = to;
Change(root->left, from, to);
Change(root->right, from, to);
}
void postOrder(TNode* n){
if ( n ) {
postOrder(n->left);
postOrder(n->right);
pArray[i] = n->data;
i++;
}
}
What am I doing wrong here?
I'm going to assume that you've verified the heap before you print it. Your tree implementation is a bit confusing, but it looks like it should work. I would suggest, however, that the first thing you do is print the tree before calling your Change method, just to make sure that you have a valid heap.
Assuming that you have a valid heap, your Change method has a problem: it never calls Heapify. You end up changing values in the heap and not rearranging. So of course it's going to be out of order when you output it.
When you change an item's value, you have to move that node (or the node's value) to its proper final position in the tree before you change any other value. You can probably make that work with your current model (by calling Heapify repeatedly until the node is in its proper position). Provided that you're increasing the value. If you're decreasing the value (i.e. changing 20 to 10), then you have a problem because your code has no way to move an item up the tree.
As #noobProgrammer pointed out in his comment, a binary heap typically is implemented as an array rather than as a tree. It's a whole lot easier to implement that way, uses less memory, and is much more efficient. If you're interested in how that's done, you should read my multi-part blog series on heaps and priority queues. The first entry, Priority queues, describes the problem. From there you can follow the links to learn about binary heaps and how they're implemented. The code samples are in C#, but if you read the first two introductory articles and understand the concepts, you'll be able to convert to C++ without trouble.

Trouble in traversing BST

I started learning about trees and tried writing the code for BST. Unfortunately i am having trouble displaying the tree datas. I am trying to implement Depth-first traversal. But have no idea how to implement it. Below is my code
#include<iostream>
using namespace std;
class node
{
public:
int data;
node *left,*right;
};
class btree
{
private:
node *root;
public:
btree(){root=NULL;}
void insert(int value)
{node *temp=new node;
if(root == NULL)
{
temp->right=NULL;
temp->data=value;
temp->left=NULL;
root=temp;
}
else
insertHelper(root, value);
}
void insertHelper(node* Node, int value)
{
if(value < Node->data)
{
if(Node->left == NULL)
{
Node->left=new node;
Node->left->data=value;
Node->left->left=NULL;
Node->left->right=NULL;
}
else
insertHelper(Node->left, value);
}
else
{
if(Node->right== NULL)
{
Node->right = new node;
Node->right->data=value;
Node->right->left=NULL;
Node->right->right=NULL;
}
else
insertHelper(Node->right, value);
}
}
void disp()
{node*tmp=root;
if(tmp==NULL)
cout<<"empty"<<endl;
else
{
cout<<tmp->data<<endl;
disphelper(tmp);
}
}
void disphelper(node *tmp)
{
if(tmp->left!=NULL)
{
cout<<tmp->left->data<<endl;
tmp=tmp->left;
disphelper(tmp);}
if(tmp->right!=NULL)
{
cout<<tmp->right->data<<endl;
tmp=tmp->right;
disphelper(tmp);
}
}
};
int main()
{
btree binarytree;
binarytree.disp();
binarytree.insert(10);
binarytree.insert(5);
binarytree.insert(30);
binarytree.disp();
}
the output is
empty
10
5
Can anyone please tell me why 30 is not displayed?
MODIFY your code to
void disphelper(node *tmp)
{
if(tmp == NULL)
return;
cout<<tmp->data<<endl; // print data for current node
if(tmp->left!=NULL) // traverse left branch
{
//cout<<tmp->left->data<<endl;
//tmp=tmp->left;
disphelper(tmp->left);}
if(tmp->right!=NULL) // traverse right branch
{
//cout<<tmp->right->data<<endl;
//tmp=tmp->right;
disphelper(tmp->right);
}
}
And it should work.
void disp()
{node*tmp=root;
if(tmp==NULL)
cout<<"empty"<<endl;
else
{
disphelper(tmp);
}
}
The reason you're not getting any output here is that in disphelper() you are first checking whether the left node is NULL and then changing it when you recurse into it. Same when you recurse into the right node.
void disphelper(node *tmp)
{
if(tmp->left!=NULL)
{
cout<<tmp->left->data<<endl;
//tmp=tmp->left; // Get rid of this.
disphelper(tmp->left); // Use this.
}
if(tmp->right!=NULL)
{
cout<<tmp->right->data<<endl;
//tmp=tmp->right; // Get rid of this
disphelper(tmp->right); // Use this.
}
}
Instead of changing the value of temp, which should be the same for both comparisons, just pass the left or right node in.
Two other things. Firstly, you're leaking memory like mad here: In your insert(), you create a new object every time, but only use it the first time, every other time it leaks. Your node class should be taking care of memory by having a destructor which deletes both nodes.
Secondly, before you post code, could you please take the trouble to format it so that the indentation is consistent? It's not the pain it use to be to do this - a lot of editors will do it for you or you can use the excellent Astyle. I know it's a small point but it's irritating for those who read your code - including, presumably the guy who's going to mark you homework! Thanks :-)

Deleting from Binary Tree error

I wrote a small code to detect the largest number in the binary tree, it is working just fine, its simple, it goes far down to the last right node(leaf in case) and then i just cout<< it, now i would like to delete it, i looked trough some similar question, but i only need to delete the number i got back from the search, but my prog just crashes after i run it list the tree get the number, delete and try to list it again.
Here is my search:
T Remove( Node* theRoot)
{
if ( root == NULL )
{
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
return Largest(theRoot->rChildptr);
else
delete theRoot;
return theRoot->data;
}
Here is the full code:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot)
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);
}
void PrintTree(Node* theRoot)
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" \n";
PrintTree(theRoot->rChildptr);
}
}
T Largest( Node* theRoot)
{
if ( root == NULL )
{
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
return Largest(theRoot->rChildptr);
else
delete theRoot;
return theRoot->data;
}
T Remove(Node* theRoot)
{
if ( root == NULL )
{
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
return Largest(theRoot->rChildptr);
else
delete theRoot;
return ;
};
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
//void Remove()
//{
// Remove(root);
//}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(2);
myBT->AddItem(20);
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(10);
myBT->AddItem(15);
//for(int i = 0; i < 10; i++) //randommal tolti fel
//myBT->AddItem(rand() % 100);
cout << "BinaryTree:" << endl; //kilistazaa a fat
myBT->PrintTree();
cout << "Largest element: " << myBT->Largest() << endl; //visszaadja a legnagyobb elemet
//myBT->Remove();
myBT->PrintTree();
}
the actual delete function is in // comments so i can run the prog.
You are deleting theRoot and then trying to dereference it. If you want to return the value stored in the node you need to make a local copy first like this:
T value = theRoot->data;
delete theRoot;
return value;
Is the return thetRoot->data; line intended to be part of the else statement? If so you need to add brackets around it like this:
if (theRoot->rChildptr != NULL)
{
return Largest(theRoot->rChildptr);
}
else
{
T value = theRoot->data;
delete theRoot;
return value;
}
Or simply remove the else case altogether (since you always return if the child pointer is null):
if (theRoot->rChildptr != NULL)
{
return Largest(theRoot->rChildptr);
}
T value = theRoot->data;
delete theRoot;
return value;
You will also need to make sure that the parent node does not still point to a deleted child (hard to see exactly what is going on because you haven't posted much code).
You cannot simply delete the object you don't want -- you must also remove the reference you used to find the node that you are deleting. And, if the node has any children, you must reattach the child nodes elsewhere to the tree so that they remain reachable.
The thing that makes it so tricky is that you have to properly update: the parent's reference to the node being deleted; one of the 'child' pointers for one of the children of the deleted node; and the parent links from both children of the deleted node. If you perform the updates out-of-order, you'll read a stale pointer and perhaps corrupt memory, so you must wait to remove nodes until you do not need any more references from within the node and you've removed references to the node from elsewhere.
Update
Don't forget that "the last right node" can in fact be the root of your tree:
5
4
3
2
1
5 is the largest, right-most, node of your tree, and if you delete it, you've lost your entire tree.
Unless you're doing some re-balancing that we're not seeing here; if you are, be sure you also handle this case:
2
1
Our friends at Wikipedia have been very kind to analyze how to delete a node from a binary search tree:
Deleting a leaf (node with no children): Deleting a leaf is easy, as we can simply remove it from the tree.
Deleting a node with one child: Remove the node and replace it with its child.
Deleting a node with two children: Call the node to be deleted N. Do not delete N. Instead, choose either its in-order successor node
or its in-order predecessor node, R. Replace the value of N with the
value of R, then delete R.
Your delete code must handle all three of these cases. Don't forget that the node you're deleting might be the root of the tree and not have a parent node.
Can you post the entire program so that it can be compiled. But basically the problem is that when theRoot->rChildptr is NULL you are deleting theRoot and then your return statement tries to return theRoot->data which is pointing to nowhere.

c++ binarysearchtree insert

I'm working on a project where I have to make a binary search tree that stores strings and takes account of doubles. While i've already tackled the specifics, I can't for the life of me get this damn insert function to work. It seems to only store the root node, leaving it's "children" NULL even though it does actually seem to assign the left and right pointers to new nodes. However when I attempt to output it, only the main parent (root) node exists. I guess the changes do not get saved for whatever reason.
Here's the header file:
#ifndef BST_H
#define BST_H
#include <string>
#include <vector>
#include <iostream>
using namespace std;
typedef string ItemType;
class Node
{
public:
Node(); // constructor
ItemType data; // contains item
Node* left; // points to left child
Node* right;// points to right child
int dataCount; // keeps track of repeats
vector<int> lineNumber; // keeps track of line numbers
};
class Tree
{
public:
Tree(); // constructor
// ~Tree(); // destructor. not working.
bool isEmpty(); // tests for empty tree
Node* find(Node* root, ItemType item); // finds an item
void insert(Node* root, ItemType item, int lineN, Tree tree); // inserts an item
void outputTree(Node* root); // lists all items in tree
void treeStats(Tree tree); // outputs tree stats
void clearTree(); // erases the tree (restart)
Node* getRoot(); // returns the root
void setRoot(Node*& root);
// void getHeight(Tree *root); // gets height of tree
private:
Node* root; // root of tree
int nodeCount; // number of nodes
};
#endif
cpp:
#include "BST.h"
bool setRootQ = true;
/** Node constructor- creates a node, sets children
* to NULL and ups the count. */
Node::Node()
{
left = right = NULL;
dataCount = 1;
}
/** Tree constructor- creates instance of tree
* and sets parameters to NULL */
Tree::Tree()
{
root = NULL;
nodeCount = 0;
}
/** Destructor- deallocates tree/node data;
* avoids heap leaks. SOMETHING WRONG. CAUSES SEGFAULT
Tree::~Tree()
{
if(this->root->left) // if a left child is present
{
delete this->root->left; //recursive call to destructor ("~Tree(->left)")
this->root->left = NULL;
}
if(this->root->right) // if a right child is present
{
delete this->root->right; //recursive call to destructor
this->root->right = NULL;
}
} */
/** Returns true if tree is empty.
* Otherwise returns false (DUH). */
bool Tree::isEmpty()
{
return root == NULL;
}
/** Searches tree for item; returns the node if found
* #param root- tree node.
* item- data to look for. */
Node* Tree::find(Node* root, ItemType item)
{
if(root == NULL) // if empty node
{
return NULL;
}
else if(item == root->data) // if found
{
return root;
}
else if(item < root->data) // if item is less than node
{
find(root->left, item);
}
else if(item > root->data) // if item is more than node
{
find(root->right, item);
}
return NULL;
}
/** Adds a new node to the tree. If duplicate, increases count.
* #param item- data to insert.
* root- tree node/ */
void Tree::insert(Node* root, ItemType item, int lineN, Tree tree)
{
Node* temp = find(tree.getRoot(), item);
if(temp != NULL) // if item already exists
{
temp->dataCount += 1;
temp->lineNumber.push_back(lineN);
return;
}
if(root == NULL) // if there is an empty space
{
root = new Node; // insert new node
root->data = item; // w/ data value
root->lineNumber.push_back(lineN);
nodeCount++;
if(setRootQ)
{
setRoot(root);
setRootQ = false;
}
return;
}
if(item < root->data)
{
insert(root->left, item, lineN, tree);
}
if(item > root->data)
{
insert(root->right, item, lineN, tree);
}
}
/** Outputs tree to console in inorder.
* #param root- tree root. */
void Tree::outputTree(Node* root)
{
if(isEmpty()) // if empty tree
{
cout << "Error: No items in tree" << endl; // error message
}
else
{
if(root->left != NULL)
{
outputTree(root->left);
}
cout << "- " << root->data << " (" << root->dataCount << ") line#s: ";
for(unsigned int i = 0; i < root->lineNumber.size(); i++)
{
cout << root->lineNumber[i] << ", ";
}
cout << endl;
if(root->right != NULL)
{
outputTree(root->right);
}
}
}
/** Displays tree stats including number of nodes,
* tree height, and more frequent item.
* #param tree- tree instance. */
void Tree::treeStats(Tree tree)
{
cout << "Number of entries: " << nodeCount << endl;
// unfinished
}
/** Clears tree.
void Tree::clearTree()
{
this->~Tree();
} */
/** Returns the root of the tree. */
Node* Tree::getRoot()
{
return root;
}
void Tree::setRoot(Node*& rootS)
{
root = rootS;
}
I realize my destructor isn't working but I'll tackle that myself later. I've been pulling my hair out over this trying to figure out what I'm missing, but to no avail. If anyone can give me any help and point me in the direction towards a solution I would greatly appreciate it.
i think it might have something to do with
void Tree::insert(Node* root, ItemType item, int lineN, Tree tree)
and instead should be something like
void Tree::insert(Node* &root, ItemType item, int lineN, Tree tree)
but when i try i get a "no matching function" error. :/
The solution you suggest yourself (with insert() taking Node *& root) will work. You have to make a corresponding change to the .h file, AND also change getRoot() to return Node *& in both .h and .cc files.
This will work. But your code has other problems. For example, setRoot and setRootQ don't do anything useful, as far as I can tell. The fourth argument to insert() only confuses things and does nothing to detect duplicates. It should be removed. To detect a duplicate simply do if (item == root->data) just before you do if (item < root->data) in the insert() method (i.e. it'll be even more similar to find()).
Also, if anyone besides you will ever use your code, you shouldn't require passing in getRoot() to methods like find() and insert(). Instead, create private helper methods, like find_helper(Node*, Item) and insert_helper(Node*&,Item), and have the public methods call them with the root node as the first argument. E.g.:
Node *find(Item item) { return find_helper(root, item); }
This would also make the weird return type of getRoot() unnecessary, and you could change it back to returning the plain Node*, or get rid of that accessor altogether.
Seems like there is a lot of pointer comparison occurring but the pointer member variables are not being initialized. Ensure that the pointer member variables are initialized properly so that they evaluate properly in if statements.
Change from:
class Node
{
public:
Node(); // constructor
...
};
to
class Node
{
public:
Node() : left(0), right(0) {}
...
};