From f2a8d58b24b2a7989a841fe7bef0332dfcdb3a3a Mon Sep 17 00:00:00 2001 From: hodasemi Date: Wed, 1 May 2019 10:44:24 +0200 Subject: [PATCH] Add iteration and unique check --- exercise1/main.cpp | 20 +++++++++- exercise1/node.cpp | 96 +++++++++++++++++++++++++++++++++++++--------- exercise1/node.h | 29 ++++++++------ 3 files changed, 113 insertions(+), 32 deletions(-) diff --git a/exercise1/main.cpp b/exercise1/main.cpp index f8ae7ad..cc77e2b 100644 --- a/exercise1/main.cpp +++ b/exercise1/main.cpp @@ -2,7 +2,8 @@ #include "node.h" -int main() { +int main() +{ /* Node* root = new Node("root"); Node* left_child = new Node("left child"); @@ -14,11 +15,26 @@ int main() { delete root; */ - Node* auto_root = Node::create_complete_tree(2, 4); + /* + Node *auto_root = Node::create_complete_tree(2, 4); std::cout << auto_root << std::endl; delete auto_root; + */ + + // cycle test + Node *root = new Node; + Node *child1 = new Node; + Node *child2 = new Node; + + root->add_child(child1); + root->add_child(child2); + + // add cycle + child1->add_child(root); + + std::cout << root << std::endl; return 0; } diff --git a/exercise1/node.cpp b/exercise1/node.cpp index 5524510..7f4a0fe 100644 --- a/exercise1/node.cpp +++ b/exercise1/node.cpp @@ -2,7 +2,7 @@ uint32_t Node::node_id = 0; -Node::Node(const std::string& name) +Node::Node(const std::string &name) { node_id++; @@ -24,7 +24,7 @@ Node::~Node() { std::cout << "enter ~node() of \"" << name << "\"" << std::endl; - for (Node* child : children) + for (Node *child : children) { delete child; } @@ -37,7 +37,7 @@ std::string Node::get_name() const return name; } -void Node::set_name(const std::string& new_name) +void Node::set_name(const std::string &new_name) { name = new_name; } @@ -47,7 +47,7 @@ int Node::get_nr_children() const return children.size(); } -Node* Node::get_child(int i) const +Node *Node::get_child(int i) const { if (i < 0 || i >= static_cast(children.size())) { @@ -57,15 +57,14 @@ Node* Node::get_child(int i) const return children[i]; } -void Node::add_child(Node* child) +void Node::add_child(Node *child) { children.emplace_back(child); } -void Node::print(std::ostream& str, uint32_t depth) const +void Node::print(std::ostream &str, uint32_t depth) const { - auto predicate = [&str](const Node* node, uint32_t depth) - { + auto predicate = [&str](const Node *node, uint32_t depth) { for (uint32_t i = 0; i < depth; i++) { str << "\t"; @@ -74,21 +73,21 @@ void Node::print(std::ostream& str, uint32_t depth) const str << node->get_name() + "\n"; }; - Node::traverse_tree(this, predicate); + Node::traverse_tree(this, predicate, false); } -Node* Node::create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth) +Node *Node::create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth) { if (tree_depth == 0) { return nullptr; } - Node* node = new Node; + 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); + Node *child = Node::create_complete_tree(nr_child_nodes, tree_depth - 1); if (child == nullptr) { @@ -101,17 +100,78 @@ Node* Node::create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth) return node; } -void Node::traverse_tree(const Node* node, std::function predicate, uint32_t depth) +void Node::traverse_tree(const Node *node, std::function predicate, bool recursive, uint32_t depth) { - predicate(node, depth); - - for (Node* child : node->children) + if (recursive) { - Node::traverse_tree(child, predicate, depth + 1); + std::set visited; + traverse_tree_recursive(node, predicate, visited, depth); + } + else + { + traverse_tree_iterative(node, predicate, depth); } } -std::ostream& operator<<(std::ostream &os, const Node *node) +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); diff --git a/exercise1/node.h b/exercise1/node.h index d23be1d..89175ba 100644 --- a/exercise1/node.h +++ b/exercise1/node.h @@ -6,31 +6,36 @@ #include #include #include +#include -class Node { +class Node +{ -public: - Node(const std::string& name = ""); + public: + Node(const std::string &name = ""); virtual ~Node(); std::string get_name() const; - void set_name(const std::string& new_name); + void set_name(const std::string &new_name); int get_nr_children() const; - Node* get_child(int i) const; - void add_child(Node* child); + Node *get_child(int i) const; + void add_child(Node *child); - void print(std::ostream& str = std::cout, uint32_t depth = 0) const; - static Node* create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth); - static void traverse_tree(const Node* node, std::function predicate, uint32_t depth = 0); + void print(std::ostream &str = std::cout, uint32_t depth = 0) const; + static Node *create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth); + static void traverse_tree(const Node *node, std::function predicate, bool recursive, uint32_t depth = 0); -private: + private: std::string name; - std::vector children; + std::vector children; static uint32_t node_id; + + static void traverse_tree_recursive(const Node *node, std::function predicate, std::set &visited, uint32_t depth = 0); + static void traverse_tree_iterative(const Node *node, std::function predicate, uint32_t depth = 0); }; -extern std::ostream& operator<<(std::ostream &os, const Node *node); +extern std::ostream &operator<<(std::ostream &os, const Node *node); #endif // NODE_H \ No newline at end of file