BinaryTree Node Class in C++ - c++

I am trying to build a node class for binary tree implementation. Here is the header file for Node class:
class Node {
public:
Node();
Node(int value);
void setParent(Node& parent);
void setLeftChild(Node& child);
void setRightChild(Node& child);
void setValue(int value);
void setIndex(int index);
void setHeight(int height);
private:
int value;
Node& parent;
Node& leftChild;
Node& rightChild;
int height;
int index;
};
Now, I want to write the constructor Node(int value) declared above.
How shall I initialize the leftChild, rightChild, parent fields? They are also Node(s), so I want to call default constructor on them but it does not seem to work.
Node::Node(int value) : value(value), parent(), leftChild(), rightChild(){
}
Compiler is saying that "reference to type 'Node' needs an initializer"
Thanks.

You should use a constructor which specify the parent of the node:
Node(Node *parent, int value);
When you create the root node you simply call this contructor with NULL as parameter.
All the reference to parent and childs should be pointers.

In this case it makes sense to use pointers over references and initialize them to NULL. By doing this you may also check if a node has a child or parent (i.e. is not root node) by checking for a NULL pointer. Also, be sure to add a destructor to deallocate memory.

You could better use pointers (Node*) instead of references (Node&). And in constructor just assign nullptr to them.
References are neccessary to reference some object (and obviously when you don't have a left or right child you can't reference them). So pointers come here to help you - they allow point to nothing - in this case nullptr is used as nothing.

Related

Calling parent function from another function using child C++

So I have a parent Class which is:
class Node
{
public:
Node();
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node);
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
And a child inheriting from that class:
class Cube : public Node
{
public:
Cube();
};
Now I have another file which has a function that uses the child class:
#include "cube.h"
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube c;
mainCube.addChildNode(c);
}
}
Problem is that mainCube doesn't see the addChildNode function which the parent has. What is the point of inheriting from another class if the parents functions aren't accessible from another place using the child class?
No, the parent classes public functions are callable from the child object.
However, the prototype of the function is
void Node::addChildNode(Node node);
So it's taking a Node object & not a Cube object.
So your compiler cannot find a function which takes a Cube object & hence the error.
The fix is to use a pointer to Node or reference to Node while declaring/defining the function.
So you function should be
void addChildNode(Node & node);
In which case, the Node object can be passed to the function & the compiler will find it.
Even better would be to have
// if you aren't looking to modify the passed object inside addChildNode
void addChildNode(const Node & node);
The following is fine & hence the function will work
Cube b;
Node &a = b;
or
Node * pn = &b;
The derived classes should be able to see the addChildNode function if you keep the signature of the function aligns. This is not a big issue. However, there are a few more "serious" issues with your code:
You need to make the base class' destructor virtual to avoid some undefined behaviors.
You have to design the ownership of nodes carefully. I guess you want the Node class to own and manage its children nodes. That means function addChildNode actually takes the ownership of the passed in node object, and it should also be deleted during destruction.
In function addCubes(), there is a loop that keeps calling addChildNode function but passes the local variable Cube c; which will be out of scope and destroyed after the loop. Thus, the parent object mainCube will holds pointers to already destroyed objects, and it will cause a crash.
After fixing all these issues, your code looks like this:
class Node
{
public:
Node() {};
virtual ~Node() {
for(auto n: childNodes) delete n;
};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<Node*> getChildNodes(){return this->childNodes;}
void addChildNode(Node* node) {
childNodes.push_back(node);
};
void removeNode();
private:
std::vector<Node*> childNodes;
Node* parentNode = nullptr;
};
class Cube : public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
Cube *c = new Cube();
mainCube.addChildNode(c);
}
}
It is preferred to use smart pointers to manage memory, and the code is more elegant and easier to read, and it makes it harder to make mistakes :-).
#include <memory>
class Node
{
public:
Node() {};
virtual ~Node() {};
void setParentNode(Node* parent) {this->parentNode = parent;}
Node* getParentNode() {return this->parentNode;}
std::vector<std::shared_ptr<Node>>& getChildNodes(){return this->childNodes;}
void addChildNode(std::shared_ptr<Node> node) {
childNodes.push_back(std::move(node));
};
void removeNode();
private:
// childNodes own elements in it, they will be deleted automatically.
std::vector<std::shared_ptr<Node>> childNodes;
Node* parentNode = nullptr;
};
class Cube: public Node
{
public:
Cube() {};
};
void addCubes(){
Cube mainCube;
for(int i = 0; i < 10; i++){
auto c = std::make_unique<Cube>();
mainCube.addChildNode(std::move(c));
}
}
Assuming that you have shared the entire implementation of your code. You have not defined the body of the function addChildNode, similar to setParentNode etc. You need to do something like childNodes.push_back(node); inside that function.
Note: It is also necessary that you pass the input to addChildNode as shown in the answer by #user93353. Also, define childNodes as std::vector<Node *> in order to avoid object slicing.

Alternative to template variables?

I'm building a binary search tree. As the generic person I am, I want to allow all types to be able to act as keys to nodes in the tree.
So I came up with the following:
class foo
{
private:
template<class T>
struct node
{
T key;
node* left;
node* right;
};
node<>* _root; //point of interest
public:
//.....
template<class T>
void insert(const T& key);
};
As I insert the nodes into the tree, I can create node objects according to the type of the key, but I don't know how to declare the _root in such a way (when using insert on an empty tree, I can easily pick the type for _root).
I believe C++14's template variables can help me here, but unfortunately MSVC's compiler hasn't implemented that feature yet.
Question: How do I declate _root in the most generic way? How did people do it in the past?
Just storing nodes is not a problem:
class foo
{
struct node
{
virtual ~node() {}
node * left;
node * right;
}
template<typename T>
struct key_node: node
{
T key;
~value_node() {}
}
node *root;
};
The problem will come when you want to access the key value within a node (because you will need to store the type information somehow).
Alternately, you can use boost::any instead of a T template:
class foo
{
struct node
{
boost::any key;
node * left;
node * right;
}
node *root;
};
... and use the interface of boost::any to get the value of they key (but even here you will probably need information on the type stored in any before you can access it in a generic way).

Would making a binary search tree out of a struct over a class node be bad?

I'm not sure if i should.. or should not use a struct to create a binary search tree, the other option is to create the nodes out of a separate node class. with a data, left and right. Which one is better? And why?
heres my code for the BST
template <typename T>
class BST : public SearchableADT<T>
{
public:
BST(void){ head = NULL; numnodes = 0; }
virtual ~BST(void);
virtual int loadFromFile(string filename);
virtual void clear(void);
virtual void insertEntry(T info);
virtual void deleteEntry(T info);
virtual bool isThere(T info);
virtual int numEntries(void);
//needed for comparison to AVL
int BST<T>::height(t_node* tPTR);
protected:
struct t_node
{
string data;
t_node *L;
t_node *R;
};
int numnodes;
t_node* head;
t_node* cPTR; //current pointer
t_node* pPTR; //parent pointer
t_node* tPTR; //temporary pointer
}; // end of class BST
I'm not sure if you understand the difference between struct and class but basically:
struct
Has public access for all of its members by default and
class
Has private access for all of its members by default.
You can achieve the same thing with both of them but many programmers, including myself, tend to use structs for POD objects (Plain Old Data) for straight up access (It makes it easier to write less).
That said, I think you should put your Node class outside in a different file since the BST and Node classes are very different. Since you gave your BST class a template, I am assuming that you are gonna use more than just the Node class, which gives more reason to separate the files for the projects that you might not use the Node class. If you aren't going to use more than just a Node class, you might consider removing the template and defining the Node struct/class inside the BST class!
It is better to create two classes, one for the BST and another for the node. They are two different abstractions. A node is a simpler abstraction whose main purpose is to hold the data necessary to define a BST. A BST is a higher level abstraction. It's a collection class with its own constraints and expectations.

Have I to call delete in this destructors?

Have I to call delete in this classes' destructors?
2 pointers to Node:
class Node {
private:
char Ch;
int Key;
Node* L;
Node* R;
public:
Node() { L = NULL; R = NULL; }
Node(char, int, Node*, Node*);
~Node();
};
Vector of pointers to Node:
class Example {
private:
vector<Node*> A;
public:
Node() {}
Node(vector<Node*>);
~Node();
};
In another class of my project I allocate Nodes through "new"!
If you allocate the nodes using new then you will eventually need to delete them, e.g. vector does not delete them for you, it only clears up the vector itself but not what the elements point to (since you have a vector of pointers). As you can tell the ownership of a node can be a bit tricky to establish in your classes - what class should delete? That is why using smart pointers like shared_ptr<> and unique_ptr<> make your life much easier.
e.g.
std::shared_ptr<Node> L;
std::shared_ptr<Node> R;
and
std::vector<std::shared_ptr<Node>> A;
then you do not need to worry about deleting

Null Object Pattern, Recursive Class, and Forward Declarations

I'm interested in doing something like the following to adhere to a Null Object design pattern and to avoid prolific NULL tests:
class Node;
Node* NullNode;
class Node {
public:
Node(Node *l=NullNode, Node *r=NullNode) : left(l), right(r) {};
private:
Node *left, *right;
};
NullNode = new Node();
Of course, as written, NullNode has different memory locations before and after the Node class declaration. You could do this without the forward declaration, if you didn't want to have default arguments (i.e., remove Node *r=NullNode).
Another option would use some inheritence: make a parent class (Node) with two children (NullNode and FullNode). Then the node example above would be the code for FullNode and the NullNode in the code above would be of type NullNode inheriting from Node. I hate solving simple problems by appeals to inheritence.
So, the question is: how do you apply Null Object patterns to recursive data structures (classes) with default arguments (which are instances of that same class!) in C++?
Use extern:
extern Node* NullNode;
...
Node* NullNode = new Node();
Better yet, make it a static member:
class Node {
public:
static Node* Null;
Node(Node *l=Null, Node *r=Null) : left(l), right(r) {};
private:
Node *left, *right;
};
Node* Node::Null = new Node();
That said, in both existing code, and amendments above, you leak an instance of Node. You could use auto_ptr, but that would be dangerous because of uncertain order of destruction of globals and statics (a destructor of some global may need Node::Null, and it may or may not be already gone by then).
I've actually implemented a recursive tree (for JSON, etc.) doing something like this. Basically, your base class becomes the "NULL" implementation, and its interface is the union of all interfaces for the derived. You then have derived classes that implement the pieces- "DataNode" implements data getters and setters, etc.
That way, you can program to the base class interface and save yourself A LOT of pain. You set up the base implementation to do all the boilerplate logic for you, e.g.
class Node {
public:
Node() {}
virtual ~Node() {}
virtual string OutputAsINI() const { return ""; }
};
class DataNode {
private:
string myName;
string myData;
public:
DataNode(const string& name, const string& val);
~DataNode() {}
string OutputAsINI() const { string out = myName + " = " + myData; return out; }
};
This way I don't have to test anything- I just blindly call "OutputAsINI()". Similar logic for your whole interface will make most of the null tests go away.
Invert the hierarchy. Put the null node at the base:
class Node {
public:
Node() {}
virtual void visit() const {}
};
Then specialize as needed:
template<typename T>
class DataNode : public Node {
public:
DataNode(T x, const Node* l=&Null, const Node* r=&Null)
: left(l), right(r), data(x) {}
virtual void visit() const {
left->visit();
std::cout << data << std::endl;
right->visit();
}
private:
const Node *left, *right;
T data;
static const Node Null;
};
template<typename T>
const Node DataNode<T>::Null = Node();
Sample usage:
int main()
{
DataNode<char> a('A', new DataNode<char>('B'),
new DataNode<char>('C'));
a.visit();
return 0;
}
Output:
$ ./node
B
A
C