#include "node.h" #include uint32_t Node::node_id = 0; Node::Node(const std::string &name) { ++this->node_id; this->name = name; } Node::Node() { ++this->node_id; std::stringstream str_sm; str_sm << "node_"; str_sm << this->node_id; this->name = str_sm.str(); } Node::~Node() { std::cout << "enter ~node() of \"" << this->name << "\"" << std::endl; for (Node *child : this->children) { delete child; } std::cout << "leave ~node() of \"" << this->name << "\"" << std::endl; } std::string Node::get_name() const { return this->name; } void Node::set_name(const std::string &new_name) { this->name = new_name; } int Node::get_nr_children() const { return this->children.size(); } Node *Node::get_child(int i) const { if (i < 0 || i >= static_cast(this->children.size())) { return nullptr; } return this->children[i]; } void Node::add_child(Node* child) { this->children.emplace_back(child); } void Node::print(std::ostream& stream) const { std::set set; this->print(stream, 0, set); }; // std::string(times, " "); void Node::print(std::ostream& stream, int level, std::set& 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); stream << repeat(" ", level * 3) << this->get_name() << std::endl; for (; i < count; ++i) { this->get_child(i)->print(stream, level + 1, set); } } } Node *Node::create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth) { if (tree_depth == 0) { return nullptr; } Node* node = new Node(); if (tree_depth == 1) { return node; } for (uint32_t i = 0; i < nr_child_nodes; ++i) { node->add_child(create_complete_tree(nr_child_nodes, tree_depth - 1)); } return node; } void Node::traverse_tree(const Node *node, std::function predicate, bool recursive, uint32_t depth) { if (recursive) { std::set 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 predicate, std::set &visited, uint32_t depth) { if (visited.find(node) != visited.end()) { return; } predicate(node, depth); visited.insert(node); for (Node *child : node->children) { Node::traverse_tree_recursive(child, predicate, visited, depth + 1); } } void Node::traverse_tree_iterative(const Node *node, std::function predicate, uint32_t depth) { struct NodeInfo { const Node *node; uint32_t depth; }; std::set visited; std::vector 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); } } } std::ostream &operator<<(std::ostream &os, const Node *node) { node->print(os); return os; } 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(); }