Binary Tree with class in c++ - c++

I'm trying to write class for binary tree in c++ but I think in inserting function I have some problem it doesnt work correctly I'm begginer in c++ and I can't find the problem.
I should write this code without using "struct" it should Compeletly write with classes
I'm so sorry beacuse my code doesn't have any comment
and also sorry for bad English
Thank you very much
#include<iostream>
using namespace std;
///////////////////////////////////////////////////////////////////////////
class Tree
{
public:
Tree* left;
Tree* right;
string info;
Tree()
{
this->left=NULL;
this->right=NULL;
this->info="";
}
Tree(string info)
{
this->left=NULL;
this->right=NULL;
this->info=info;
}
Tree(string info,Tree* left,Tree* right)
{
this->left=left;
this->right=right;
this->info=info;
}
};
/////////////////////////////////////////////////////////////////////
class LinkedList
{
public:
Tree* root;
LinkedList()
{
root=NULL;
}
void mainInsert(Tree* newroot , string info)
{
if(newroot==NULL)
{
Tree* newNode = new Tree(info);
newroot=newNode;
return;
}
if(info.compare(newroot->info)==-1)
{
mainInsert(newroot->left,info);
}
else
{
mainInsert(newroot->right,info);
}
}
void mainPrintTree(Tree* newroot)
{
if(newroot==NULL)
{
return;
}
cout<<newroot->info<<endl;
mainPrintTree(newroot->left);
mainPrintTree(newroot->right);
}
void insert(string info)
{
mainInsert(this->root , info);
}
void printTree()
{
mainPrintTree(this->root);
}
};
///////////////////////////////////////////////////////////////////////////
int main()
{
LinkedList myTree;
myTree.insert("2");
myTree.insert("1");
myTree.insert("3");
myTree.insert("7");
myTree.insert("0");
myTree.printTree();
return 0;
}

Here is a (the?) culprit:
void mainInsert(Tree* newroot, string info)
{
if (newroot == NULL)
{
Tree* newNode = new Tree(info);
newroot = newNode; // Oops, only changing a local pointer here!
return;
}
...
It is a common error of beginners: you passed a pointer to a function, change that pointer and wonder why the original pointer is still unchanged... The reason is that apart from being able to change its pointee value, a pointer is a mere variable. So the function has its local copy of the pointer, and changing it has no effect in the caller. Here a simple way is probably to return the new root:
Tree* mainInsert(Tree* newroot, string info)
{
if (newroot == NULL)
{
Tree* newNode = new Tree(info);
return newNode;
}
// remember to return newroot in other branches...
Just use that in insert:
void insert(string info)
{
this->root = mainInsert(this->root , info);
}
But there are tons of possible improvements here, like separating the public interface from the private implementation, so I would advise you to post your code on Code Review as soon as is will work without errors...

Your mainInsert is wrong: after mainInsert(newroot->left,info);, newroot->left is not modified because that argument is passed by value (BTW read this SO article article, it's about C, not C++ but the concept is the same).
The simplest here is just to pass the node by reference, which makes your code even simpler:
void mainInsert(Tree* &subTree, string info)
{
if (subTree == NULL)
{
subTree = new Tree(info);
return;
}
if (info.compare(subTree->info) == -1)
{
mainInsert(subTree->left, info);
}
else
{
mainInsert(subTree->right, info);
}
}
I renamed the newroot parameter into subTree, because there is actually only one root per tree and every node of the tree is actually a also tree.
BTW: your question about writing this code without using struct is pointless, you don't use struct at all in your code.
Hint: try to write an iterative version of mainInsert. It's pretty simple and straightforward as the problem is not inherently recursive.

Related

C++ Binary Search Tree Insert Implementation

I'm trying to build a function to insert into a binary search tree, but I'm having a hard time figuring out why it won't work. I understand fundamentally how the function is supposed to work, but based on the template I was given it seems as though I am to avoid creating a BST class but instead rely on the Node class and build the desired functions to work on that. Here's the given template:
#include <iostream>
#include <cstddef>
using std::cout;
using std::endl;
class Node {
int value;
public:
Node* left; // left child
Node* right; // right child
Node* p; // parent
Node(int data) {
value = data;
left = NULL;
right = NULL;
p = NULL;
}
~Node() {
}
int d() {
return value;
}
void print() {
std::cout << value << std::endl;
}
};
function insert(Node *insert_node, Node *tree_root){
//Your code here
}
The issue I'm having is when I implement the following code, where getValue is a simple getter method for Node:
int main(int argc, const char * argv[]) {
Node* root = NULL;
Node* a = new Node(2);
insert(a, root);
}
void insert(Node *insert_node, Node *tree_root){
if (tree_root == NULL)
tree_root = new Node(insert_node->getValue());
The code appears to compile and run without error, but if I run another check on root after this, it returns NULL. Any idea what I'm missing here? Why is it not replacing root with a new node equal to that of insert_node?
I also realize this doesn't appear to be the optimal way to implement a BST, but I am trying to work with the template given to me. Any advice would be appreciated.
As Joachim said your issue relates to difference between passing parameter by reference and by value.
In your code void insert(Node *insert_node, Node *tree_root) you pass Node* tree_root by value. Inside the function you change local copy of this pointer, so outer value is not changed.
To fix it you should pass Node* tree_root by reference. Parameter declaration can be Node*& tree_root (or Node** tree_root). E.g:
void insert(Node* insert_node, Node*& tree_root){
if (tree_root == NULL)
tree_root = new Node(insert_node->getValue());

How to pass the value from superclass to subclass in c++

I have made a superclass named "tree". I have constructed the tree in this class. Now, I want to pass the root of the constructed tree to another class which is a subclass of tree. But when I try to pass it, the subclass calls the supercalss constructor and sets it to NULL;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
This is the definition of my tree class. It just creates a tree with one node having value 5. Now I want to pass the new root created to a subclass of tree.
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
I create an object for tree first and then do createtree. Now, when I create an object for treeiterator, it's member p gets sets to NULL since supercalss constructor is also called. How can I just access the tree created in the superclass in subclass?
Full code:
#include <bits/stdc++.h>
using namespace std;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
void treeiterator::push(struct node *t)
{
while(t) {
s.push(t);
t = t->left;
}
}
bool treeiterator::hasnext()
{
return s.empty()?1:0;
}
int treeiterator::next()
{
struct node *t = s.top();
int val = t->val;
s.pop();
if(t->right) {
push(t->right);
}
return val;
}
int main()
{
tree t;
t.createtree();
t.preorder();
treeiterator it;
while(it.hasnext()) {
cout<<it.next()<<' ';
}
}
Because of inheritance every treeiterator is also a tree. This means
treeiterator treeIt;
treeIt.createtree();
will do what OP wants. There is no need to make a separate tree and moving the root around.
However this is a bit odd in the world of C++ because OP is under-using the constructor. For example, node could be:
struct node
{
node *left;
node *right;
int val;
node(int inval):
val(inval),
left(nullptr),
right(nullptr)
// the above is a Member Initializer List. It makes sure all of your
// members are initialized before the body of the constructor runs.
{
}
};
That bit after the : in the constructor is the Member Initializer List.
Now when you allocate a node it's initialized and ready to be linked. For tree
class tree
{
public:
struct node *root; // almost certainly should not be public.
// also should be a std::unique_ptr<node>
tree(int inval)
{
root = new node(5); // note new in place of malloc. new allocates
// storage and calls constructors. malloc should
// only be used in C++ in rare edge-cases.
}
/* obsolete
void createtree()
{
root = create(5);
}
*/
...
};
tree is assigned a root on allocation. treeiterator is a wee bit trickier because it must call tree's constructor to set up root.
class treeiterator:public tree
{
struct node *p; // Don't see the point off this
stack<struct node *> s; // or this, but that's another question
public:
treeiterator(int inval):
tree(inval) // call's tree's constructor
{
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
Allocating a treeiterator now guarantees that it is all ready to go with no further work.
treeiterator treeIt(5); // all done.
All of the above is covered within the first few chapters of any good C++ programming text. I recommend getting one and reading it, because right now it looks like you are trying to write bad C.
Off topic 1:
You are going to quickly find that this code is in violation of the Rule Of Three. What is The Rule of Three? If you don't know, read the link. It will save you much time and hair-pulling
Off Topic 2:
#include <bits/stdc++.h>
using namespace std;
Is a ticking time bomb. The first line includes the entire standard library, but only in GCC. Your code is now doing far, far more work than it need to to compile, is no longer standard C++, and is not portable to other compilers and may well break with the next revision of GCC. Don't use anything in bits. It internal compiler-specific stuff with no guarantees what-so-ever.
More here: Why should I not #include <bits/stdc++.h>?
The second line takes everything in the std namespace and places it in the global namespace. This leads to fun games like is reverse or std::reverse being called? Often this leads to insane and arcane compiler messages because the poor compiler is confused as hell, but sometimes it's not confused and picks the best choice among the many and silently breaks something else. Great fun debugging.
More here: Why is "using namespace std" considered bad practice?
Together you have the entire standard library pulled into your file AND stripped of it's proper namespace. This results in a vast minefield of potential hidden pain that is not worth any perceived time savings. One of the resulting bugs could cost more clean up than years of typing a few extra lines per file and characters.
No one want to clean up code with this stupid a mistake, so doing this in a professional setting can be costly.
First, you should not have root has public. This is a gross OO error. If you want it to be available to subclasses you should make it protected.

Deleting all from trie tree

I always seem to get in trouble when I'm deleting all nodes from a tree. I am trying to release all the memory I allocated when creating a trie tree.
I am suppose to create a function remove_all
Is it enough to delete just the "root"
something like this:
void PrefixStringSet::remove_all(NodePtr node)
{
delete root;
}
Or do I have to delete each node with something like this:
void PrefixStringSet::remove_all(NodePtr node)
{
if(!root)
{
return;
}
remove_all(root->children);
delete root;
}
Obviously neither of these are working or I wouldn't be here :).
Other question. Do I have to call the remove_all function in my main function if my destructor is implemented like this
PrefixStringSet::~PrefixStringSet()
{
remove_all(root);
}
Or does the destructor automatically delete the trees/nodes I create?
Edit
struct TrieNode
{
TrieNode(bool present = false);
bool is_leaf();
bool present;
TrieNode* children[ALPHABET_SIZE];
};
class PrefixStringSet
{
public:
// Creates an empty prefix string set.
PrefixStringSet();
~PrefixStringSet();
bool insert(string s);
bool contains(string s);
private:
NodePtr root;
void remove_all(NodePtr node);
};
typedef TrieNode* NodePtr;
Deleting only root is not enough: when deleting a root, you should check whether its children aren't empty, and if they are not empty, recursively delete them. C++ doesn't have garbage collector to do the work for you :)
If your remove_all method is within the destructor of the wrapper object, then you don't have to call it separately.
You should write a remove method in all classes you want to delete at runtime.
So you can delete a tree with little care about garbage collection.
It's easy to use pointer in this way:
class a
{
public:
a(){}
~a(){remove();}
init(int v){
var = new int;
*var=v; }
remove(){delete var;}
private:
int *var;
};
class b
{
public:
b(){}
~b(){remove();}
init(int v){
var = new a;
var->init(v); }
remove(){
var->remove();
delete var; }
private:
a *var;
};
To answer your question: No, deleting root is not enough.
edit: sry i made a mistake at a:init(). I forgot to derefer the pointer.
In Cpp:
void deleteAll(Node* curNode) {
for (int i = 0; i < 26; i++) {
if (NULL != curNode->child[i]) {
deleteAll(curNode->child[i]);
}
}
delete curNode;
}
deleteAll(root);

First time using classes in C++, what's going on?

I am trying to implement a custom tree structure, but I am getting a weird output.
enum letter{B,A,T,G,C,N};
struct Node {
int ltr;
Node* ptr;
};
class GTree
{
public:
GTree(int);
void insert(int);
private:
Node* root;
void insert(int l,Node* leaf);
};
GTree::GTree(int l)
{
root->ltr=l;
}
void GTree::insert(int l, Node *leaf)
{
cout<<leaf->ltr;
}
void GTree::insert(int l)
{
if(root==NULL)
{
insert(l, root);
}
else
{
root= new Node;
insert(l,root);
}
}
int main()
{
GTree tree=GTree(T);
tree.insert(T);
}
The output comes out as -2062064467 even though I was expecting 2. Whats going on here? I was looking at a simple BTree implementation, but intending to repurpose it for my desired data structure.
You didn't create a Node object when you first created the GTree object.
GTree::GTree(int l)
{
root->ltr=l;
}
should be
GTree::GTree(int l)
{
root = new Node();
root->ltr=l;
}
Also, make sure you have a destuctor to clean up the resources.
Something else I feel I should point out is that GTree::insert(int l, Node *leaf) perhaps doesn't do what you expect it to do.
cout<<leaf->ltr;
The code above only outputs the integer value in the node but not actually assigning it.
But perhaps you haven't completed that part yet. :-)
You hadn't initialized root, so root->ltr=l; produces undefined behavior. Add root = new Node(); first.
I ran your code and got the output 0 on Ubuntu 12.04 with gcc 4.6.3.

Recursively inserting into a binary tree, passing pointer by value?

Here is my Node class.
class Node
{
private:
public:
T data;
Node<T>* left;
Node<T>* right;
Node(T dat) : data(dat), left(NULL), right(NULL)
{}
};
Here is my insert function, defined in my Btree class:
public:
Node<T>* root;
Btree() : root(NULL){}
void insert(T data, Node<T>* parent)
{
if( !parent )
{
parent = new Node<T>(data);
return;
}
else if(data < parent->data)
{
insert(data, parent->left);
}
else if(data > parent->data)
{
insert(data, parent->right);
}
}
};
Here is my main function:
int main()
{
Btree<int> tree;
tree.insert(5, tree.root);
cout << tree.root->data << endl;
tree.insert(6, tree.root);
cout << tree.root->right->data << endl;
}
When I run, I get a seg fault.
I think it is because the pointer variable parent is passed by value, so when I create a new Node that is pointed to by parent, once I exit the insert function I lose it? Does that mean I have to use a double pointer here?
Can someone give me a thorough explanation about what's going on in memory that is making this not work out as planned. Is my diagnosis correct here or is there something else wrong?
When I pass tree.root as the second parameter to insert, I am passing a Node*, I know that much. Now, even if it is passed by value, will it not be the same address that I passed from the invoking main function. So when I say parent (which is the address which I passed from main, tree.root) = new Node, should that not create a new Node on the heap that at the address of parent, aka the address of tree.root? Why does passing by value fudge this up?
The problem with passing by value in this case is that all assignments made to the formal argument inside the function are not visible to the caller. Therefore, this assignment
if( !parent )
{
parent = new Node<T>(data); // <<== HERE
return;
}
has no effect on the tree.root in the caller:
tree.insert(5, tree.root);
The value of the parent pointer in the function is changed, and then promptly discarded; tree's root remains NULL.
A fix to this problem would be passing a pointer to a pointer, like this:
void insert(T data, Node<T>** parent) {
if( !*parent )
{
*parent = new Node<T>(data);
return;
}
else if(data < (*parent)->data)
{
insert(data, &((*parent)->left));
}
else if(data > (*parent)->data)
{
insert(data, &((*parent)->right));
}
}
C++ passes by value, so that parent is a copy of the passed-in pointer. Assigning to it therefore has no lasting effect. The easiest way to fix this is to change the signature of the method so that it accepts a reference to the pointer. This will automatically make the compiler update the original pointer while avoiding having to the change the rest of the program.
dasblinkenlight answered it best. But, there is a more succinct solution:
Get the reference of the pointer (known as reference to pointer):
void insert(T data, Node<T>*& parent)
{
if( !parent )
{
parent = new Node<T>(data);
return;
}
else if(data < parent->data)
{
insert(data, parent->left);
}
else if(data > parent->data)
{
insert(data, parent->right);
}
}
See more here:
http://www.codeproject.com/Articles/4894/Pointer-to-Pointer-and-Reference-to-Pointer