ECG/exercise1/node.cpp

202 lines
4.1 KiB
C++
Raw Normal View History

2019-04-19 12:00:50 +00:00
#include "node.h"
2019-05-08 11:07:37 +00:00
#include <set>
2019-04-19 12:00:50 +00:00
uint32_t Node::node_id = 0;
2019-05-01 08:44:24 +00:00
Node::Node(const std::string &name)
2019-04-19 12:00:50 +00:00
{
2019-05-08 11:07:37 +00:00
++this->node_id;
this->name = name;
}
2019-04-19 12:00:50 +00:00
2019-05-08 11:07:37 +00:00
Node::Node()
{
++this->node_id;
2019-04-19 12:00:50 +00:00
2019-05-08 11:07:37 +00:00
std::stringstream str_sm;
str_sm << "node_";
str_sm << this->node_id;
this->name = str_sm.str();
2019-04-19 12:00:50 +00:00
}
Node::~Node()
{
2019-05-08 11:07:37 +00:00
std::cout << "enter ~node() of \"" << this->name << "\"" << std::endl;
2019-04-19 12:00:50 +00:00
2019-05-08 11:07:37 +00:00
for (Node *child : this->children)
2019-04-19 12:00:50 +00:00
{
delete child;
}
2019-05-08 11:07:37 +00:00
std::cout << "leave ~node() of \"" << this->name << "\"" << std::endl;
2019-04-19 12:00:50 +00:00
}
std::string Node::get_name() const
{
2019-05-08 11:07:37 +00:00
return this->name;
2019-04-19 12:00:50 +00:00
}
2019-05-01 08:44:24 +00:00
void Node::set_name(const std::string &new_name)
2019-04-19 12:00:50 +00:00
{
2019-05-08 11:07:37 +00:00
this->name = new_name;
2019-04-19 12:00:50 +00:00
}
int Node::get_nr_children() const
{
2019-05-08 11:07:37 +00:00
return this->children.size();
2019-04-19 12:00:50 +00:00
}
2019-05-01 08:44:24 +00:00
Node *Node::get_child(int i) const
2019-04-19 12:00:50 +00:00
{
2019-05-08 11:07:37 +00:00
if (i < 0 || i >= static_cast<int>(this->children.size()))
2019-04-19 12:00:50 +00:00
{
return nullptr;
}
2019-05-08 11:07:37 +00:00
return this->children[i];
2019-04-19 12:00:50 +00:00
}
2019-05-08 11:07:37 +00:00
void Node::add_child(Node* child) {
this->children.emplace_back(child);
2019-04-19 12:00:50 +00:00
}
2019-05-08 11:07:37 +00:00
void Node::print(std::ostream& stream) const
2019-04-19 12:00:50 +00:00
{
2019-05-08 11:07:37 +00:00
std::set<const Node*> set;
this->print(stream, 0, set);
};
2019-04-19 12:00:50 +00:00
2019-05-08 11:07:37 +00:00
// std::string(times, " ");
void Node::print(std::ostream& stream, int level, std::set<const Node*>& set) const
{
int i = 0;
int count = this->get_nr_children();
if (set.find(this) != set.end())
{
stream << repeat(" ", level * 3) << this->get_name() << " (cycle)" << std::endl;
}
else
{
set.insert(this);
2019-04-19 12:00:50 +00:00
2019-05-08 11:07:37 +00:00
stream << repeat(" ", level * 3) << this->get_name() << std::endl;
for (; i < count; ++i)
{
this->get_child(i)->print(stream, level + 1, set);
}
}
2019-04-19 12:00:50 +00:00
}
2019-05-01 08:44:24 +00:00
Node *Node::create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth)
2019-04-19 12:00:50 +00:00
{
if (tree_depth == 0)
{
return nullptr;
}
2019-05-08 11:07:37 +00:00
Node* node = new Node();
2019-04-19 12:00:50 +00:00
2019-05-08 11:07:37 +00:00
if (tree_depth == 1)
2019-04-19 12:00:50 +00:00
{
2019-05-08 11:07:37 +00:00
return node;
}
2019-04-19 12:00:50 +00:00
2019-05-08 11:07:37 +00:00
for (uint32_t i = 0; i < nr_child_nodes; ++i)
{
node->add_child(create_complete_tree(nr_child_nodes, tree_depth - 1));
2019-04-19 12:00:50 +00:00
}
return node;
}
2019-05-01 08:44:24 +00:00
void Node::traverse_tree(const Node *node, std::function<void(const Node *, uint32_t)> predicate, bool recursive, uint32_t depth)
{
if (recursive)
{
std::set<const Node *> visited;
traverse_tree_recursive(node, predicate, visited, depth);
}
else
{
traverse_tree_iterative(node, predicate, depth);
}
}
void Node::traverse_tree_recursive(const Node *node, std::function<void(const Node *, uint32_t)> predicate, std::set<const Node *> &visited, uint32_t depth)
2019-04-19 12:00:50 +00:00
{
2019-05-01 08:44:24 +00:00
if (visited.find(node) != visited.end())
{
return;
}
2019-04-19 12:00:50 +00:00
predicate(node, depth);
2019-05-01 08:44:24 +00:00
visited.insert(node);
for (Node *child : node->children)
2019-04-19 12:00:50 +00:00
{
2019-05-01 08:44:24 +00:00
Node::traverse_tree_recursive(child, predicate, visited, depth + 1);
}
}
void Node::traverse_tree_iterative(const Node *node, std::function<void(const Node *, uint32_t)> predicate, uint32_t depth)
{
struct NodeInfo
{
const Node *node;
uint32_t depth;
};
std::set<const Node *> visited;
std::vector<NodeInfo> stack;
NodeInfo info = {.node = node, .depth = 0};
stack.emplace_back(info);
while (!stack.empty())
{
// get the last node and remove it from the stack
NodeInfo current = stack.back();
stack.pop_back();
// check if we already visited this node
if (visited.find(current.node) != visited.end())
{
continue;
}
// execute given function
predicate(current.node, current.depth);
// mark this node as visited
visited.insert(current.node);
// push children to the stack
for (auto child = current.node->children.rbegin(); child != current.node->children.rend(); child++)
{
NodeInfo info = {.node = *child, .depth = current.depth + 1};
stack.emplace_back(info);
}
2019-04-19 12:00:50 +00:00
}
}
2019-05-01 08:44:24 +00:00
std::ostream &operator<<(std::ostream &os, const Node *node)
2019-04-19 12:00:50 +00:00
{
node->print(os);
return os;
2019-05-08 11:07:37 +00:00
}
std::string repeat(std::string value, int times)
{
std::stringstream str_sm;
for (int i = 0; i < times; ++i) {
str_sm << value;
}
return str_sm.str();
}