Create special binary search tree using C++ - c++

I want to create a Binary search tree which has special Nodes. There should be three classes of Nodes, Internal Node, External Node and Root node, each inheriting a common parent Node and each type of node will have some unique function. Is it possible to create such a BST. The problem I am facing is suppose the first node I insert into the tree becomes the root node. The next node I insert will become External Node. Now if I insert another node then the external node has to become a internal node and the new node will become the external node. Also I cannot find a way to navigate through the tree from one node to another as the nodes will be of different types. Can a tree of this type be created. If yes then give me some suggestions of how this can be done.

If I understand correctly, you're worried about how objects in one class - External - need to become objects of another class - Internal. This, when C++ is a statically-typed language: Types (including the classes of objects) are determined at compile-time. Right?
Well, you can achieve this in at least one of two ways:
When an External node becomes Internal, delete the External node and replace it with an Internal node, properly initialized (e.g. to point at the new External node).
Give up on External and Internal being discrete types, and just check for children and parents to determine the node type dynamically.
Some more relevant reading material on these matters:
(Programming language) type systems in this Wikipedia page.
This SO question: What is duck typing?
The Circle-vs-Eclipse problem, and specifically the desire to stretch circles into ellipses.

You could use basic inheritance some type enum and recursive calls.
This could be a starting point:
enum NodeType
{
eRoot,
eInternal,
eExternal
};
class BinaryNode
{
public:
virtual NodeType GetType() = 0;
virtual void UpdateTree() = 0;
protected:
BinaryNode* ChildLeft;
BinaryNode* ChildRight;
BinaryNode* Parent;
};
class ExternalNode : public BinaryNode
{
NodeType GetType() override { return eExternal; }
void UpdateTree() override
{
//... Replace node instances here(e.g. delete this node and construct the correct new one given this sub tree. call new InternalNode(this) for example)
// Call this towards the parent node so the tree will be transformed accordingly
}
}
class InternalNode : public BinaryNode
{
NodeType GetType() override { return eInternal; }
void UpdateTree() override { //... }
}
class RootNode : public BinaryNode
{
NodeType GetType() override { return eRoot; }
void UpdateTree() override { //... }
}
This is just to give you an idea where to start. You can check the node type at runtime via GetType() and do some checks based on that.
Be aware that this kind of transformation is not particularly fast.
If you want this to be fast, don't use different types and virtual function calls and pointers.
Place your binary tree inside an array and use binary indexing, so at a given index "n" use 2*n+1 to get the left child and 2*n+2 to get the right child. Then use some flags (root, external, internal etc.) to determine which functions you want to call on the binary node. I wouldn't use inheritance like in my code example to be fast or more readable. In fact, deciding externally what functions to call on a node can be much more readable and less error-prone.

Related

C++ n-arry tree with different elements

I want to build a n-arry tree from a document. For that i have 3 different types of elements for the tree:
Struct Nodes
Have a name
can contain other Nodes
Depth
Element Node (Leaf of the tree)
Have a Key
Have a value
Depth
Element Template Node (Leaf of the tree)
Have a placeholder which should be resolved later in the program
Depth
At the moment i think about something like this:
class Node {
public:
Node(int depth);
int depth() const;
private:
int depth_;
};
class StructNode : public Node {
...
private:
std::vector<std::unique_ptr<Node>> children;
};
class ElementNode : public Node {
...
};
class ElementTemplateNode : public Node {
...
};
The Tree will be generated from an File on Startup and reused to create an output string like this:
Structname:
key = value
key = value
Structname:
key = value
Structname:
key = value
...
Where the Key and value where directly read from the ElementNode or read from another file with the value of the placeholder inside the ElementTemplateNode
Is there maybe a better Structure for the Tree? Because with the current one i have to check first if its a StructNode, ElementNode or ElementTemplateNode
This is a typical structure for implementing a tree with different kind of nodes. Another variant would be the composite pattern.
The problem that you describe, is usually caused by asking the nodes about what they know, instead of telling them what to do. If you'd do it the other way round (tell, don't ask), you could get rid of those checks and benefit from polymorphism.
The different kind of nodes inherit from Node. You could design your tree using a uniform interface, with virtual functions defined for Node which then can be overridden for the different types of nodes. Calling the method would then do the right things, without need for a manual type check. For generating the output string, you'd tell the root node to generate a string. If it's a structure, it would add the heading and tell its children to generate a string, but if it's a leaf it would just add the key/value pair to the string. No need from outside to know anything about each node.
If the operation of exploring the tree shall not be implemented by the tree itself, the usual approach is to use a visitor pattern. The big advantage is that you write the vistor once, and it's then easy to specialize a new kind of visitor for different algorithms. Again, no need to check the type of the nodes. The pattern makes sure that the right elementary function is called for the right type of node.

Converting subclass to base class?

I am working on a problem in which we have a binary search tree made of nodes. The node's attributes consist of string, pointer to left node, and pointer to right node. I have a class called TransactionNode that is a subclass of node. TransactionNode has an int (for amount sold) as well as the same attributes from node class. I have a function called findBiggest that looks for the highest amount sold from TransactionNode and returns a reference to that TransactionNode. My problem is how do I convert something that is from the node class to TransactionNode? (I am avoiding changing the nodes in the binary search tree to TransactionNodes)
TransactionNode & BST::findBiggest()
{
TransactionNode * rightSide;
rightSide = this->mpRoot;
while (rightSide != nullptr)
{``
//find biggest transaction
}
return rightSide;
}
In general, if you need to check if an object pointed to by a base class pointer is of the derived class type, you use dynamic_cast
In your case you could try inside your while loop:
TransactionNode* txnNode = dynamic_cast<TransactionNode*>(rightSide);
if (txnNode != nullptr)
{
int amtSold = txnNode->GetAmountSold();
}
You may also consider having a virtual method in the base class and rely on polymorphism. Usually that is a preferred way over dynamic_cast. However, it may be that your Node class is too high level and does not need to support a "GetAmountSold()" method, but that is something you can decide.

Design and implementation of a 2-3 tree with polymorphism

I have to implement a 2-3 tree using a base class of a node and derived class of leaf and an innernode (i.e both "are-a" node).
But I don't understand how to start with the insertion in simple cases. Since we call the methods of node to insert, how is it supposed to know if what we insert needs to be an innernode or a leaf? And how does a node supposed to change itself to a leaf or an innernode?
Any tips/ideas on how to approach this?
Here's the structure, I didn't get very far though.
typedef int TreeKey;
class node {
public:
virtual ~node() {}
virtual void insert(TreeKey k, string d);
virtual void deletenode(TreeKey k);
virtual void findnode();
virtual node * findnode(TreeKey key);
protected:
struct info {
TreeKey key;
string data;
};
node* parent=nullptr;
};
class leaf : node {
info i;
public:
virtual void insert(TreeKey k, string d);
};
class innerNode : node {
vector<info> inf;
vector<node*> vect;
public:
virtual void insert(TreeKey k, string d);
};
Note: in this 2-3 tree, the data sits only in the leaves.
One way of doing things is as follows. There are others.
Have 4 separate classes: a 2-leaf-node, a 3-leaf-node, a 2-internal-node and a 3-internal-node. This solution gets rid of vectors and so minimises dynamic allocations.
One inserts an element, not a node. Each node knows what to do with inserted element. An internal node passes the element to one of the child nodes. A leaf node absorbs the element.
A 2-node absorbs an element by becoming a 3-node. A 3-node absorbs an element by becoming two 2-nodes, and passing an element back to its parent to absorb. The parent then itself changes and may pass an element up. This continues until some 2-node changes to a 3-node (its parent doesn't need to change, only replace its child pointer), or an element propagates all the way back to the root, and a new root is created.
How a node "becomes" something else? It cannot. Instead, it creates the new thing(s) it should become, copies its information to the new thing(s), returns the newly created thing(s) to the caller, and deletes itself. The caller then either replaces its old child with the newly created one, or itself "becomes" something else.
The insert method signature of the node could look like this:
typedef enum {none, expand23, split322} action;
action Node::insert(info& element, Node*& newNode1, Node*& newNode2);
If the node was a 2-node and it became a 3-node, the method creates a new 3-node and passes it back in newNode1. The parent has to replace the corresponding child pointer upon seeing expand23. The parent itself doesn't expand or split, so its insert returns none.
If the node was a 3-node and it splits, the method creates two new 2-nodes and passes them back in newNode1 and newNode2. It also passes back an element for that the parent to absorb. The parent will do either expand23 or split322 depending on what type it is.
If the root returns split322, a new root is created
"in this 2-3 tree, the data sits only in the leaves" — just noticed this remark. I'm not sure how this could ever work. A 2-3 tree has either 1 or 2 data items in each node, not just leaves. It cannot work otherwise. So I pretty much ignore this remark.
If you don't want to have separate classes for 2- and 3-nodes, then you don't need expand23 because a 2-node can turn into a 3-node without having to delete itself. split322 remains the same. I would not use vectors in this case. Since leaf nodes only store copies of keys that exist elsewhere, they can be stored as 3 (smart) pointers to keys (not an array, just 3 separate variables). You distinguish between a 2-node and a 3-node by looking at the third pointer. If it's a nullptr, this is a 2-node. Same thing about data in the leaves, store it in 3 separate pointers.

Combine two base class instances into a derived one

I have the following classes I used to define a tree structure with a number of specific nodes
class TreeNode
{
std::vector<TreeNode*> children;
}
class BTNode: public virtual TreeNode
{
virtual bool loadAttributes(XML) = 0;
virtual BTState tick() = 0;
void otherFunction1() { used by all the different nodes}
void otherFunction2() { also used by all the node types }
}
There are a couple of specific implementations of the BTNode class that can be saved and loaded from XML files:
class BTSpecificNodeOne: public BTNode
{
bool loadAttributes(XML) { load node specific data from XML }
BTState tick() { specific implementation goes here }
}
class BTSpecificNodeTwo: public BTNode
{
bool loadAttributes(XML) { load node specific data from XML }
BTState tick() { specific implementation goes here }
}
etc.
I also have a genetic algorithm that optimises this tree structure based on a common tree node genome type:
class TreeNodeGenome: public virtual TreeNode
{
bool load(XML);
TreeNodeGenome* crossover(TreeNodeGenome* other);
virtual void mutate() = 0;
}
Furthermore, to have the node specific implementation used within the genome
class BTSpecificNodeGenomeOne: public BTSpecificNode, public TreeNodeGenome
{
void mutate() { node specific implementation }
}
class BTSpecificNodeGenomeTwo: public BTSpecificNode, public TreeNodeGenome
{
void mutate() { node specific implementation }
}
etc.
I'd like to be able to save and load the results of the optimisation to/from an XML file.
The implementations of BTSpecificNodeOne, BTSpecificNodeTwo, etc. already have a save/load function that I use for saving the results, but loading them is a bit more tricky.
The load function of the BTNode class rebuilds the tree (from XML) based on the BTNode class (nodes may create children that are also loaded recursively). In order to use it again in the genetic algorithm, I need the nodes to derive from the TreeNodeGenome class as well.
I can rebuild a TreeNodeGenome structure based only on the information contained in TreeNode, but I'm not sure how to "merge" these two trees together.
I know that I could pretty much copy the load functions into the BTSpecificNodeGenomeOne, BTSpecificNodeGenomeTwo, etc. classes but I was wondering if there is a simpler/cleaner way to do it?
EDIT: Apparently what I'd like to do is a bit unclear from my previous post.
I have implemented a Behaviour Tree(BT) class, which uses a number of different nodes deriving from BTNode: Selector, Sequence, different condition and action nodes. The BT itself is saved in an XML format and can be loaded via BTNode::loadAttributes().
In addition to this, I have a genetic algorithm that can optimise tree structures. TreeNodeGenome implements the genetic operators of the different nodes to be used during evolution.
During evolution I use BTSpecificNodeGenomeOne, BTSpecificNodeGenomeTwo nodes that implement both the different BT nodes and the genetic operators from TreeNodeGenome. TreeNodeGenome requires only the structure of the tree already encoded in the TreeNode base class and the node specific implementations of the mutation operator. As the BT and an evolvable tree structure are two conceptually different things, I'd like to keep them separate.
My question is: I have the BTNode::loadAttributes() function implemented for all BTNodes already, which load the BT from an XML file. This function creates its children as BTNodes, which are not evolvable. If I want to use the loaded tree in evolution, I need to somehow "merge" it with a TreeNodeGenome object.
I can do this by reimplementing the loadAttributes function in each derived BTSpecificNodeGenome, but I was wondering if there was a cleaner/simpler way to do this?

Design choice regarding manipulation of main loop from treegraph

I'm creating a simple game for programming practice on bigger projects and am currently stuck at a crossroad.
The game uses a treegraph structure to store all the entities of the game, all extending from the base class called TreeNode that implements some basic functions such as attaching and detaching children from themselves as well as their position in the 2D world.
My problem is that I want to create a sort of "Action Node" that upon collision with the player allows various events to take place, such as changing the song being played, trigger a pause with subsequent dialogue, ending the stage etc etc.
My question is, how would i implement this in a decent way that doesn't beat my efforts of code isolation to a bloody pulp? I was thinking of making a new class with a std::function member that i can program to do what i want it to do, but that way would mean completely breaking code encapsulation by handing it a reference to my master class that contains ALL data in the entire game.
Collision is currently implemented something like this:
std::vector<std::pair<&TreeNode, &TreeNode>> vCollision;
MasterNode.checkCollision(vCollision);
checkCollision gets called with a reference to the vector, invokes collision checks recursively on the rest of the graph and fills the vector with pairs of different entities that have collided. (this is in the update loop.)
I also need to figure out a way to be able to call said std::function from this list since pointers to the base class wont have access to members of derived classes.
A tree structure is a container that can be used with different data types. Because of this, it is a good candidate for templates.
Since you have your tree working, factor out the data type to a template parameter.
For example, given a node:
struct Tree_Node
{
struct Tree_Node * left_subtree;
struct Tree_Node * right_subtree;
Some_Data_Type node_data;
};
You can factor out the data type using templates:
template <class Node_Data_Type>
struct Tree_Node
{
struct Tree_Node * left_subtree;
struct Tree_Node * right_subtree;
Node_Data_Type node_data;
};
You would declare a tree node as:
struct Player_Data;
Struct Moves_Data;
struct Tree_Node<Player_Data>; // For a tree of Player_Data
struct Tree_Node<Moves_Data>; // For a tree of Moves_Data
An alternative is to use inheritance for the node data.
struct Node_Data_Base
{
virtual bool is_equal(Node_Data_Base * p_node) const = 0;
virtual bool is_less(Node_Data_Base * p_node) const = 0;
bool operator==(Node_Data_Base * p_node) const
{
return is_equal(p_node); // Dispatch to child.
}
bool operator<(Node_Data_Base * p_node) const
{
return is_less(p_node); // dispatch to child.
}
};
struct Tree_Node_Inheritance
{
struct Tree_Node * left_subtree;
struct Tree_Node * right_subtree;
Node_Data_Base * p_data;
};
Also, review the std::map data type.