I tried searching for this problem on stackoverflow but couldn't find it, so pardon me if it already existed.
So, what I wish to do is to create a function that traverses a tree and returns a pointer to the Node with the highest value. The Tree would be unordered and asymmetric, and will not have a fixed depth. Each node has a pointer to its Parent node, a list containing its Child nodes, and an integer named 'value'. And the tree would have a pointer to its root node, like this:
struct Node
{
private:
Node* parent;
list<Node> childs;
int value;
public:
// Getters, setters and constructors
}
struct Tree
{
private:
Node* root;
public:
// Getters, setters and constructors
}
And, as I stated before, I wish to make a function that traverses the entire tree, aka every single Node in the entire tree regardless of the depth, and returns a pointer to the node with the highest value. I assume it'll require recursion, but I can't figure out a way to do this.
Pardon me if my question seems dumb / stupid, but I really need help
You can use recursive method, which returns the pointer to the node with maximal value of current and child nodes:
struct Node
{
...
Node* getMaxNode()
{
Node* maxNode = this;
for (auto& child : this->childs) {
Node* childsMaxNode = child.getMaxNode();
if (childsMaxNode->getValue() > maxNode->getValue())
maxNode = childsMaxNode;
}
return maxNode;
}
}
If current node doesn't have child nodes, it will return pointer to the current node. So, in struct Tree you can implement something like this:
struct Tree
{
Node* getMax()
{
return this->root->getMaxNode();
}
}
Related
As part of an exercise my university has tasked me with, I have written a small Graph implementation, following this header.
class Node {
private:
std::string name;
std::vector<Node*> children;
public:
Node(const std::string& name="");
virtual ~Node();
}
When writing code for the destructor ~Node(), I noticed that my implementation fails when the graph contains a cycle. This is my implementation so far, which obviously doesn't work if the graph contains a cycle.
Node::~Node() {
for (Node* n : children) {
delete n;
n = NULL;
}
children.clear();
}
I am uncertain as to how I would most elegantly write a destructor that can handle cycles in the graph?
Please note that I was specifically tasked to write a recursive destructor.
Thank you for your answers!
Option 1: Choose a representation for the graph where nodes are not owned by other nodes, but rather the graph which would be a distinct object. This way the node destructor doesn't need to do anything. This won't satisfy the requirement of recursion:
struct Graph {
std::vector<std::unique_ptr<Node>> nodes;
};
Note that if there is no inheritance involved, then you could simply use std::vector<Node>. I assume that there is, due to the usage of virtual desturctor in Node.
Alternatively, you could use another representation for the graph such as adjacency list.
Option 2: Use an algorithm to generate a minimum spanning forest of the graph. Then recursively delete the roots of each spanning tree. You can for example use the Kruskal's algorithm. (Given your representation, it looks like your graph may be connected, in which case there would be only one spaning tree).
One option could be to first create an unordered_set of all the Node*s and then to delete them.
void fill(std::unordered_set<Node*>& to_delete, Node* ptr) {
// try to insert ptr and return if it was already in the set
if(not to_delete.emplace(ptr).second) return;
// swap ptr->children with an empty vector
std::vector<Node*> tmp;
std::swap(tmp, ptr->children);
for(Node* c : tmp) // loop over the pointers
fill(to_delete, c); // fill recursively
}
virtual ~Node() noexcept { // std::terminate if anything should throw
if(children.empty()) return; // nothing to do here
std::unordered_set<Node*> to_delete; // to collect all the Node*'s
fill(to_delete, this); // fill the set recursively
to_delete.erase(this); // don't delete "this"
for(auto c : to_delete) // delete all - they have no children by now
delete c;
}
Demo
If your graph is a tree (I assume it since your implementation of destructor is valid only for a tree) and you can store parent of the Node then you can write iterative version which do not require any extra data structure to avoid recursion.
Also learn to use smart pointers.
class Node {
private:
std::string name;
std::vector<std::unique_ptr<Node>> children;
Node* parent;
void safeCleanClildren();
public:
Node(std::string name="", Node* parent = nullptr)
: name{std::move(name)}
{}
~Node() {
iterativeCleanClildren();
}
void addChild(std::string name) {
children.emplace_back(std::make_unique<Node>(std::move(node), this);
}
};
void Node::iterativeCleanClildren()
{
auto p = this;
while (!p->children.empty()) {
while (!p->children.empty()) {
p = p->back().get(); // go as deep as possible
}
if (p != this) {
p = p->parent; // go back to parent
p->children.pop_back();
}
}
}
How this work?
first it finds leaf (right most) in a tree (node which do not have children)
Then goes back to parent node and remove child which was just found p->children.pop_back(); (this destroys unique_ptr of just found leaf).
Then finds again leaf and so on.
This tree clearing continues until root (this) node is reached
This way root node ends with no children at all and since it is iterative implementation overflown is impossible. It doesn't matter how much unbalance this tree is.
Here's a simplified version of my Node class :
class Node {
public:
Node();
// indicators of whether the node is a top or bottom node
bool Top;
bool Bot;
// pointers for tree structure
Node *Parent;
Node *LeftC;
Node *RightC;
std::list<Node*> getNodesList();
};
What I want is be able to get a list of pointers to the nodes in my tree in a certain order. I tried the following code to do this :
std::list<Node*> Node::getNodesList(){
if (Bot) return (std::list<Node*>(1,this));
else {
std::list<Node*> temp (1,this);
temp.splice(temp.end(), LeftC->getNodesVector()); // Combine with left childrens
temp.splice(temp.end(), RightC->getNodesVector()); // Combine with right childrens
return temp;
}
}
The splice function doesn't work and give me an error.
So my questions are :
Why isn't the splice function working to combine the lists?
Is there a more efficient way to return the list of pointers to the nodes?
Since I do not know the exact error you have, just a quick glance at your code tells me that your Node class probably doesn't know what getNodesVector() is since it isn't defined in your class.
I have to make an implementation of the following class in C++:
struct Node {
Node* parent;
Node* left;
Node* right;
std::string name;
};
class BinaryTree {
public:
BinaryTree();
std::string ToString() const;
void RotateLeft(Node* node);
void RotateRight(Node* node);
void MakePerfect();
private:
void CreateVine();
void MakePerfectFromVine();
private:
Node *root;
};
This class implements the DSW algorithm for making a Binary tree perfect (all levels are full, except the last one)
I have done an implementation which works, I tested it and everything seem fine but I had to change the rotate functions thus:
void RotateLeft(Node*& node);
void RotateRight(Node*& node);
Unfortunately the person who set me this task said that I'm forbidden to change them. But the unaltered functions don't work. I use them in CreateVine() and MakePerfectFromVine():
void CreateVine() {
Node *current = root;
while(current != NULL)
if(current->left != NULL){
current=current->left;
rotateRight(current);
}
else
current = current->right;
}
In this fragment the pointer current points to a node in the tree. After the node is rotated, it will have changed its parent and/or left and/or right child, but current will point to the old node with the old information. In order for the changes made in the rotate function to be reflected outside of the rotate function, I have to use reference-to-pointer, pointer-to-pointer or the function itself has to return the node;
The only way I can think of to fix this problem is if I know that the binary tree doesn't allow duplicate elements, after I rotate the node I search for its string value and set current to point to it, but I'm not sure if the binary tree doesn't allow duplicate elements and that would increase the time complexity of the algorithm.
Is there any way of avoiding the use of reference-to-pointer and pointer-to-pointer?
Excluding the root of the tree, for which you might have to think something else, the pointer to a given node inside the tree can be obtained with an extra level of indirection:
Node **pp;
if (node->parent->left == node)
pp = &node->parent->left;
else
pp = &node->parent->right;
So you can actually maintain your algorithm and just resolve the reference doing this inside the function. Note that this is a sketch, you will have to check for the root (parent==0) and operate differently there
I'm writing a program in C++ that uses genetic techniques to optimize an expression tree.
I'm trying to write a class Tree which has as a data member Node root. The node constructor generates a random tree of nodes with +,-,*,/ as nodes and the integers as leaves.
I've been working on this awhile, and I'm not yet clear on the best structure. Because I need to access any node in the tree in order to mutate or crossbreed the tree, I need to keep a dicionary of the Nodes. An array would do, but it seems that vector is the recommended container.
vector<Node> dict;
So the Tree class would contain a vector dict with all the nodes of the tree (or pointers to same), the root node of the tree, and a variable to hold a fitness measure for the tree.
class Tree
{
public:
typedef vector<Node>dict;
dict v;
Node *root;
float fitness;
Tree(void);
~Tree();
};
class Node
{
public:
char *cargo;
Node *parent;
Node *left;
Node *right;
bool entry;
dict v;
Node(bool entry, int a_depth, dict v, Node *pparent = 0);
};
Tree::Tree()
{
Node root(true, tree_depth, v);
};
There seems to be no good place to put typedef vector<Node>dict;, because if it goes in the definition of Tree, it doesn't know about Node, and will give an error saying so. I havn't been able to find a place to typedef it.
But I'm not even sure if a vector is the best container. The Nodes just need to be indexed sequentally. The container would need to grow as there could be 200 to 500 Nodes.
I think a standard Binary Tree should do... here is an example of a (binary) expression tree node:
const int NUMBER = 0, // Values representing two kinds of nodes.
OPERATOR = 1;
struct ExpNode { // A node in an expression tree.
int kind; // Which type of node is this?
// (Value is NUMBER or OPERATOR.)
double number; // The value in a node of type NUMBER.
char op; // The operator in a node of type OPERATOR.
ExpNode *left; // Pointers to subtrees,
ExpNode *right; // in a node of type OPERATOR.
ExpNode( double val ) {
// Constructor for making a node of type NUMBER.
kind = NUMBER;
number = val;
}
ExpNode( char op, ExpNode *left, ExpNode *right ) {
// Constructor for making a node of type OPERATOR.
kind = OPERATOR;
this->op = op;
this->left = left;
this->right = right;
}
}; // end ExpNode
So when you're doing crossover or mutation and you want to select a random node you just do the following:
Count the number of nodes in the tree (only need to do this ones in the constructor).
Select a random index from 0 to the size of the tree.
Visit each node and subtract 1 from the random index until you reach zero.
Return the node when the index is 0.
In this case you don't need to know anything about the parent of the node. So mating/mutation should look like this:
select nodeX
select nodeY
if( Rand(0,1) == 1 )
nodeY->left = nodeX;
else
nodeY->right = nodeX;
And that should be it...
I don't think the Node or the Tree are the first classes to write.
I'd start with Expression. In your case you need at least a BinaryExpression, as well as an expression with no subnodes (constants or variables). Each Binary expression should contain auto_ptr<Expression> lhs and auto_ptr<Expression> rhs.
You could then easily write a function to enumerate through the expression tree's members. If performance turns out to be relevant, you can cache the list of expressions in the tree, and invalidate it manually when you change the expression. Anything more advanced is likely to be slower and more error prone.
I don't see why an expression needs to know it's parent expression. It only makes life harder when you start editing expressions.
You may implement a list over nodes. Then, each node will have two additional pointers inside:
class Node{
...
Node* sequentialPrevious;
Node* sequentialNext;
...
}
And so will the tree:
class Tree{
...
Node* sequentialFirst;
Node* sequentialLast;
...
}
Than you will be albe to move bidirectionally over nodes just by jumping to sequentialFirst or sequentialLast and then iteratively to sequentialNext or sequentialPrevious. Of course, Node constructor and destructor must be properly implemented to keep those pointers up to date.
edit
Clafification: The intention is not to remove the node from the original list. But to create an identical node (data and children wise) to the original and insert that into the new list. In other words, a "move" does not imply a "remove" from the original.
endedit
The requirements:
Each Node in the list must contain a reference to its previous sibling
Each Node in the list must contain a reference to its next sibling
Each Node may have a list of child nodes
Each child Node must have a reference to its parent node
Basically what we have is a tree structure of arbitrary depth and length. Something like:
-root(NULL)
--Node1
----ChildNode1
------ChildOfChild
--------AnotherChild
----ChildNode2
--Node2
----ChildNode1
------ChildOfChild
----ChildNode2
------ChildOfChild
--Node3
----ChildNode1
----ChildNode2
Given any individual node, you need to be able to either traverse its siblings. the children, or up the tree to the root node.
A Node ends up looking something like this:
class Node
{
Node* previoius;
Node* next;
Node* child;
Node* parent;
}
I have a container class that stores these and provides STL iterators. It performs your typical linked list accessors. So insertAfter looks like:
void insertAfter(Node* after, Node* newNode)
{
Node* next = after->next;
after->next = newNode;
newNode->previous = after;
next->previous = newNode;
newNode->next = next;
newNode->parent = after->parent;
}
That's the setup, now for the question. How would one move a node (and its children etc) to another list without leaving the previous list dangling?
For example, if Node* myNode exists in ListOne and I want to append it to listTwo.
Using pointers, listOne is left with a hole in its list since the next and previous pointers are changed. One solution is pass by value of the appended Node. So our insertAfter method would become:
void insertAfter(Node* after, Node newNode);
This seems like an awkward syntax. Another option is doing the copying internally, so you'd have:
void insertAfter(Node* after, const Node* newNode)
{
Node *new_node = new Node(*newNode);
Node* next = after->next;
after->next = new_node;
new_node->previous = after;
next->previous = new_node;
new_node->next = next;
new_node->parent = after->parent;
}
Finally, you might create a moveNode method for moving and prevent raw insertion or appending of a node that already has been assigned siblings and parents.
// default pointer value is 0 in constructor and a operator bool(..)
// is defined for the Node
bool isInList(const Node* node) const
{
return (node->previous || node->next || node->parent);
}
// then in insertAfter and friends
if(isInList(newNode)
// throw some error and bail
I thought I'd toss this out there and see what folks came up with.
Let's call the node that we are going to remove current. Only the nodes pointed to by current, namely current->previous, current->next, current->child, and current->parent refer to the node current. For example, current->previous->next == current if the current node's previous node is non-null. So, we can easily excise the current node from the list like so:
Vertical Links
A node keeps its children, but it needs to be excised from its parent. This is done like so:
Let parent = current->parent
if parent is non-null:
if parent->child == current:
parent->child = current->next
current->parent = null
Horizontal Links
The following code unlinks the current node in the horizontal (next/previous) direction:
Let prev = current->previous
Let next = current->next
if prev is non-null:
prev->next = next
if next is non-null:
next->previous = prev
current->previous = null
current->next = null
Granted, this is still a bit messy, but if you break the linked list functionality into small functions (which it looks like you are already doing) and use good comments, then it's really not that bad, I don't think.
First, I agree that, if you're copying the node and not actually removing it from the original tree, the operation should be called a copy, not a move!
Second, I recommend you separate the operation that actually does the copying from the operation that does insertion. This will make it much more flexible, if say for example you need to insert nodes from other sources into your destination, or you want to copy the node for other purposes.
Third, you didn't specify whether Node is polymorphic. If it is, I would implement a method like the following to do the copy:
virtual Node* clone();
You have a couple of design decisions to make here:
Do you want to preserve next, prev, and parent when you do a clone? I think it makes sense to zero them out.
Do you want to do a deep copy of the children as well when you do a clone? Depending on the use case, you may want to do one or the other, or allow for both.
Fourth, you assume that insertion should fail if the parent/prev/next pointers are already set. You can do this, but you may benefit down the road from a more powerful insertion operation that simply removes nodes from their existing tree in this case. Either will behave consistently.
Fifth, you can't be passing const Nodes around if you're going to be fixing up that node's pointers.
Let's assume for the moment that you decide to zero out the linked list pointers but decide to deep copy the children. Then your code might look like:
class Node {
public:
Node() : prev(NULL), next(NULL), parent(NULL), child(NULL) { }
virtual Node* clone() {
Node* newN = new Node();
newN->cloneChildren(*this);
return newN;
}
Node* lastChild() const { /* left as exercise */ }
void insert(Node* node_) { insertAfter(node_, lastChild()); }
void insertAfter(Node* node_, Node* prevSibling_) {
ASSERT(node_);
if (! prevSibling_) { // assume we want to push to front of child list
prevSibling_ = child; // will be NULL if we have no children
}
ASSERT(! prevSibling_ || prevSibling_->parent == this);
if (node_->parent) {
// assume you want to move the child in this case
node_->parent->remove(node_);
}
node_->parent = this;
node_->prev = prevSibling_;
if (prevSibling_) {
node_->next = prevSibling_->next;
prevSibling_->next = node_;
} else {
/* the new child is the only child - left as exercise */
}
}
void remove(Node* child_) { /* left as exercise */ }
protected:
virtual void cloneChildren(const Node& rhs) { /* left as exercise */ }
};
And the code that does the copying from one tree to another simply looks something like:
Node* myNode = ...
Node* someChildInListTwo = findPlaceToInsert(listTwo);
listTwo->insertAfter(myNode->clone(), someChildInListTwo);
In this case we have turned your one somewhat tangled operation into a set of discrete operations that you can use in a wide variety of cases:
a clone() operation that allows you to copy arbitrary nodes, whether or not they've been added to trees yet
an insert() operation that will automatically do a move for you if you want, and correctly handles adding to the front of the child list
a remove() operation that fell out naturally as a byproduct of how we wanted insertion to behave, but which can be used on its own
a simple mechanism to copy+insert the node if you don't want to remove the node from the original tree