I just want to know if it is possible to do something like this:
#include "graph.h"
Graph A, B;
Node n;
A.insertNode(n);
A.nodeExists(n); // returns true
B.nodeExists(n); // returns false
Since now I only stored a boolean var inside Node class, which tells me if a Node object has been inserted inside a Graph. But in this way, what happens:
A.nodeExists(n); // returns true
B.nodeExists(n); // returns true
which is incorrect. How can I solve this?
Either you should store a pointer to the Graph object that the Node belongs to in the Node (thus replacing your bool by a Graph*). Then it's easy and fast to check has been assigned to a particular Graph object. Inside the Graph::nodeExists function just asK:
if (n.pOwnerGraph == this)
return true;
As an alternative you could scan your entire graph and look for the the given node. That is much slower, but it doesn't require a Graph pointer in the node.
Related
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.
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.
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.
I'm writing a k-d tree, which I think is good enough at this point. I've put the whole template at http://private.org.il/Code%20Projects/kd%20tree%20w%20bb%20cache.zipx
One thing I'd like to do is eliminate RTTI, and specifically calls to dynamic_pointer_cast.
_____________________ Edit with more info _____________________
The relevant part is that I use three classes: an abstract node class, that requires it's derived classes to implement the isInternal() function.
There are two classes that derive from it - an internal node class (function returns true), and a leaf node class (function returns false). Therefore, once isInternal is called, I know to which of the two derived classes the pointer can be casted to.
The one routine I'm having problem eliminating the call is ApproxNearestNeighborNode, which provides an initial guess for the nearest neighbor search. Currently it looks like this
shared_ptr<kd_leaf_node> ApproxNearestNeighborNode(const kd_point &srcPoint) const
{
unsigned int Depth = 0;
shared_ptr<kd_node> Node(m_Root);
while (Node->isInternal())
{
shared_ptr<kd_internal_node> iNode = dynamic_pointer_cast<kd_internal_node>(Node);
if (srcPoint[Depth++%K] <= iNode->splitVal() || iNode->Right() == nullptr)
Node = iNode->Left();
else
Node = iNode->Right();
}
shared_ptr<kd_leaf_node> lNode = dynamic_pointer_cast<kd_leaf_node>(Node);
return lNode;
}
The two issues that baffle me is keeping the routine iterative, rather than recursive, and returning a smart pointer to the leaf node.
[OK, I think there's a way to do it using shared_from_this, I just hope there's a way to do it rewriting as little code as possible.]
Any other feedback would be appreciated, but off topic, so please send it by email.
As noted by πάντα ῥεῖ, you can replace dynamic_pointer_cast by static_pointer_cast. It seems that your Node->isInternal() check is meant to ensure the dynamic case always succeeds, so a simple search-and-replace is enough.
I have the requirement to contain a pointer of same class within a class ( something like link list , containing the pointer to next link ). What my requirement is something like this :
class A
{
class A* child;
}
I want to ensure that A->child->child will always be NULL and no one can change this. ( Ensuring a link list to have no more than two nodes ).
Any help ?
Any restriction like that would be awkward (if possible). I'd go with a fixed-length array instead:
A* l[3];
if you need to prevent slicing, or simply
A l[3];
otherwise.
You could programatically enforce that restriction through something like:
class A
{
A* child;
public:
void addChild(A* newChild)
{
if ( child == NULL )
child = newChild;
else if ( child->child == NULL )
child->child = newChild;
else
throw std::exception("list is already at full capacity");
}
}
It can't be done, not using a single link anyways. If you have a link pointing back to the "parent" it might be done by having the child and parent member variables private, and then have special access functions that makes sure you can not add more than two links to the first object in the chain.
The reason I suggest using a "parent" chain is because you could force the first object in the chain to check it's child chain, but if you have access to e.g. the last object in the chain you could add two more children in that chain.