Add iteration and unique check

This commit is contained in:
hodasemi 2019-05-01 10:44:24 +02:00
parent f61fe57a40
commit f2a8d58b24
3 changed files with 113 additions and 32 deletions

View file

@ -2,7 +2,8 @@
#include "node.h" #include "node.h"
int main() { int main()
{
/* /*
Node* root = new Node("root"); Node* root = new Node("root");
Node* left_child = new Node("left child"); Node* left_child = new Node("left child");
@ -14,11 +15,26 @@ int main() {
delete root; 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; std::cout << auto_root << std::endl;
delete auto_root; 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; return 0;
} }

View file

@ -2,7 +2,7 @@
uint32_t Node::node_id = 0; uint32_t Node::node_id = 0;
Node::Node(const std::string& name) Node::Node(const std::string &name)
{ {
node_id++; node_id++;
@ -24,7 +24,7 @@ Node::~Node()
{ {
std::cout << "enter ~node() of \"" << name << "\"" << std::endl; std::cout << "enter ~node() of \"" << name << "\"" << std::endl;
for (Node* child : children) for (Node *child : children)
{ {
delete child; delete child;
} }
@ -37,7 +37,7 @@ std::string Node::get_name() const
return name; return name;
} }
void Node::set_name(const std::string& new_name) void Node::set_name(const std::string &new_name)
{ {
name = new_name; name = new_name;
} }
@ -47,7 +47,7 @@ int Node::get_nr_children() const
return children.size(); return children.size();
} }
Node* Node::get_child(int i) const Node *Node::get_child(int i) const
{ {
if (i < 0 || i >= static_cast<int>(children.size())) if (i < 0 || i >= static_cast<int>(children.size()))
{ {
@ -57,15 +57,14 @@ Node* Node::get_child(int i) const
return children[i]; return children[i];
} }
void Node::add_child(Node* child) void Node::add_child(Node *child)
{ {
children.emplace_back(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++) for (uint32_t i = 0; i < depth; i++)
{ {
str << "\t"; str << "\t";
@ -74,21 +73,21 @@ void Node::print(std::ostream& str, uint32_t depth) const
str << node->get_name() + "\n"; 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) if (tree_depth == 0)
{ {
return nullptr; return nullptr;
} }
Node* node = new Node; Node *node = new Node;
for (uint32_t j = 0; j < nr_child_nodes; j++) 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) if (child == nullptr)
{ {
@ -101,17 +100,78 @@ Node* Node::create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth)
return node; return node;
} }
void Node::traverse_tree(const Node* node, std::function<void(const Node*, uint32_t)> predicate, uint32_t depth) void Node::traverse_tree(const Node *node, std::function<void(const Node *, uint32_t)> predicate, bool recursive, uint32_t depth)
{ {
predicate(node, depth); if (recursive)
for (Node* child : node->children)
{ {
Node::traverse_tree(child, predicate, depth + 1); std::set<const Node *> 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<void(const Node *, uint32_t)> predicate, std::set<const Node *> &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<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);
}
}
}
std::ostream &operator<<(std::ostream &os, const Node *node)
{ {
node->print(os); node->print(os);

View file

@ -6,31 +6,36 @@
#include <sstream> #include <sstream>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
#include <set>
class Node { class Node
{
public: public:
Node(const std::string& name = ""); Node(const std::string &name = "");
virtual ~Node(); virtual ~Node();
std::string get_name() const; 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; int get_nr_children() const;
Node* get_child(int i) const; Node *get_child(int i) const;
void add_child(Node* child); void add_child(Node *child);
void print(std::ostream& str = std::cout, uint32_t depth = 0) const; 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 Node *create_complete_tree(uint32_t nr_child_nodes, uint32_t tree_depth);
static void traverse_tree(const Node* node, std::function<void(const Node*, uint32_t)> predicate, uint32_t depth = 0); static void traverse_tree(const Node *node, std::function<void(const Node *, uint32_t)> predicate, bool recursive, uint32_t depth = 0);
private: private:
std::string name; std::string name;
std::vector<Node*> children; std::vector<Node *> children;
static uint32_t node_id; static uint32_t node_id;
static void traverse_tree_recursive(const Node *node, std::function<void(const Node *, uint32_t)> predicate, std::set<const Node *> &visited, uint32_t depth = 0);
static void traverse_tree_iterative(const Node *node, std::function<void(const Node *, uint32_t)> 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 #endif // NODE_H