#include "node.h" uint32_t Node::node_id = 0; Node::Node(const std::string &name) { node_id++; if (name.empty()) { std::stringstream str_sm; str_sm << node_id; std::string node_id_str = str_sm.str(); this->name = "node" + node_id_str; } else { this->name = name; } } Node::~Node() { std::cout << "enter ~node() of \"" << name << "\"" << std::endl; for (Node *child : children) { delete child; } std::cout << "leave ~node() of \"" << name << "\"" << std::endl; } std::string Node::get_name() const { return name; } void Node::set_name(const std::string &new_name) { name = new_name; } int Node::get_nr_children() const { return children.size(); } Node *Node::get_child(int i) const { if (i < 0 || i >= static_cast(children.size())) { return nullptr; } return children[i]; } void Node::add_child(Node *child) { children.emplace_back(child); } void Node::print(std::ostream &str, uint32_t depth) const { auto predicate = [&str](const Node *node, uint32_t depth) { for (uint32_t i = 0; i < depth; i++) { str << "\t"; } str << node->get_name() + "\n"; }; Node::traverse_tree(this, predicate, false); } Node *Node::create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth) { if (tree_depth == 0) { return nullptr; } Node *node = new Node; for (uint32_t j = 0; j < nr_child_nodes; j++) { Node *child = Node::create_complete_tree(nr_child_nodes, tree_depth - 1); if (child == nullptr) { break; } node->children.emplace_back(child); } 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; }