10 #ifndef CTRL_UTILS_TREE_H_
11 #define CTRL_UTILS_TREE_H_
19 #include <type_traits>
20 #include <unordered_map>
24 #if __cplusplus >= 201703L
47 template <
typename Key,
typename T>
75 enum class SearchType { kDepthFirstSearch, kBreadthFirstSearch };
90 const std::unordered_map<Key, T>&
nodes()
const {
return nodes_; }
91 const std::unordered_map<Key, T>& values()
const {
return nodes_; }
99 root_view
roots() {
return root_view(
this); }
106 const T&
at(
const Key&
id)
const {
return nodes_.at(
id); }
107 T&
at(
const Key&
id) {
return nodes_.at(
id); }
167 const Key&
id, SearchType search_type = SearchType::kBreadthFirstSearch,
168 size_t max_depth = std::numeric_limits<size_t>::max()) {
179 const Key&
id, SearchType search_type = SearchType::kBreadthFirstSearch,
180 size_t max_depth = std::numeric_limits<size_t>::max())
const {
193 size_t max_depth = std::numeric_limits<size_t>::max()) {
207 SearchType search_type,
208 size_t max_depth = std::numeric_limits<size_t>::max())
const {
229 return id_parent ?
depth(*id_parent) + 1 : 0;
237 void insert(
const Key&
id,
const T& value) {
239 throw std::invalid_argument(
"Tree::insert_child(): Key already exists.");
253 throw std::invalid_argument(
"Tree::insert_child(): Key already exists.");
255 nodes_[id] = std::move(value);
267 void insert_child(
const Key& id_parent,
const Key&
id,
const T& value) {
269 throw std::invalid_argument(
"Tree::insert_child(): Key already exists.");
284 throw std::invalid_argument(
"Tree::insert_child(): Key already exists.");
286 nodes_[id] = std::move(value);
325 const_child_view
children(
const Key&
id)
const {
326 return const_child_view(
this,
id);
338 std::vector<Key>& siblings =
children_.at(*id_parent_old);
339 auto it = std::find(siblings.begin(), siblings.end(),
id);
340 if (it != siblings.end()) {
356 for (
const Key& id_child :
children_.at(
id)) {
395 for (
const auto& key_val :
ancestors(
id)) {
396 if (key_val.first == id_ancestor)
return true;
419 const std::function<std::string(
const Key& key,
const T& val)>&
420 StringifyValue)
const {
421 for (
const auto& key_val :
nodes(SearchType::kDepthFirstSearch)) {
422 const Key& key = key_val.first;
423 for (
size_t i = 0; i <
depth(key); i++) {
426 os <<
"- " << key <<
": " << StringifyValue(key, key_val.second) << std::endl;
435 for (
const auto& key_val : tree.
nodes(SearchType::kDepthFirstSearch)) {
436 const Key& key = key_val.first;
437 for (
size_t i = 0; i < tree.
depth(key); i++) {
440 os << key <<
": " << key_val.second << std::endl;
455 std::unordered_map<Key, std::optional<Key>>
parents_;
463 template <
typename Key,
typename T>
464 template <
bool Const>
467 using TreeT = std::conditional_t<Const, const Tree<Key, T>,
Tree<Key, T>>;
471 ChainView(TreeT* tree,
const Key&
id) : tree_(tree), id_(
id) {}
473 iterator begin()
const {
return iterator(tree_, id_); }
481 template <
typename Key,
typename T>
482 template <
bool Const>
485 using TreeT = std::conditional_t<Const, const Tree<Key, T>,
Tree<Key, T>>;
486 using ValueT = std::conditional_t<Const, const std::pair<const Key, T>,
487 std::pair<const Key, T>>;
490 using iterator_category = std::forward_iterator_tag;
491 using value_type = ValueT;
492 using difference_type = ptrdiff_t;
493 using pointer = value_type*;
494 using reference = value_type&;
500 iterator& operator++() {
501 id_ = tree_->parents_.at(*id_);
505 iterator operator++(
int) {
511 reference operator*()
const {
return *tree_->nodes_.find(*id_); }
513 pointer operator->()
const {
return tree_->nodes_.find(*id_).operator->(); }
515 bool operator==(
const iterator& other)
const {
516 return tree_ == other.tree_ && id_ == other.id_;
519 bool operator!=(
const iterator& other)
const {
return !(*
this == other); }
526 template <
typename Key,
typename T>
527 template <
bool Const>
530 using TreeT = std::conditional_t<Const, const Tree<Key, T>,
Tree<Key, T>>;
531 using ValueT = std::conditional_t<Const, const std::pair<const Key, T>,
532 std::pair<const Key, T>>;
535 using iterator_category = std::random_access_iterator_tag;
536 using value_type = ValueT;
537 using difference_type = ptrdiff_t;
538 using pointer = value_type*;
539 using reference = value_type&;
542 Iterator(TreeT* tree,
const std::vector<Key>* ids,
size_t idx_id)
543 : tree_(tree), ids_(ids), idx_id_(idx_id) {}
546 Iterator& operator++() {
return operator+=(1); }
554 reference operator*()
const {
return *tree_->nodes_.find((*ids_)[idx_id_]); }
556 pointer operator->()
const {
557 return tree_->nodes_.find((*ids_)[idx_id_]).operator->();
560 bool operator==(
const Iterator& rhs)
const {
561 return tree_ == rhs.tree_ && ids_ == rhs.ids_ && idx_id_ == rhs.idx_id_;
564 bool operator!=(
const Iterator& rhs)
const {
return !(*
this == rhs); }
567 Iterator& operator--() {
return operator+=(-1); }
576 Iterator& operator+=(difference_type n) {
581 Iterator operator+(difference_type n)
const {
586 Iterator& operator-=(difference_type n) {
return operator+=(-n); }
588 Iterator operator-(difference_type n)
const {
return operator+(-n); }
590 difference_type operator-(
const Iterator& rhs)
const {
591 return idx_id_ - rhs.idx_id_;
594 value_type operator[](difference_type n)
const {
return *(operator+(n)); }
596 bool operator<(
const Iterator& rhs)
const {
597 return tree_ == rhs.tree_ && ids_ == rhs.ids_ && idx_id_ < rhs.idx_id_;
600 bool operator<=(
const Iterator& rhs)
const {
601 return tree_ == rhs.tree_ && ids_ == rhs.ids_ && idx_id_ <= rhs.idx_id_;
604 bool operator>(
const Iterator& rhs)
const {
return rhs < *
this; }
606 bool operator>=(
const Iterator& rhs)
const {
return rhs <= *
this; }
609 TreeT* tree_ =
nullptr;
610 const std::vector<Key>* ids_ =
nullptr;
614 template <
typename Key,
typename T>
615 template <
bool Const>
618 using TreeT = std::conditional_t<Const, const Tree<Key, T>,
Tree<Key, T>>;
622 DescendantView(TreeT* tree,
const Key&
id, SearchType search_type,
626 search_type == SearchType::kBreadthFirstSearch
627 ? &DescendantView::AddDescendantsBfs
628 : &DescendantView::AddDescendantsDfs;
630 ids_.reserve(tree_->size());
631 (this->*AddDescendants)(
id, max_depth);
634 DescendantView(TreeT* tree, SearchType search_type,
size_t max_depth)
637 search_type == SearchType::kBreadthFirstSearch
638 ? &DescendantView::AddDescendantsBfs
639 : &DescendantView::AddDescendantsDfs;
641 ids_.reserve(tree_->size());
642 for (
const auto& key_val : tree->roots()) {
643 (this->*AddDescendants)(key_val.first, max_depth);
651 void AddDescendantsDfs(
const Key&
id,
size_t max_depth) {
652 AddDescendantsDfsDepth(
id, max_depth, 0);
655 void AddDescendantsDfsDepth(
const Key&
id,
size_t max_depth,
size_t depth) {
657 if (
depth >= max_depth)
return;
658 for (
const Key& id_child : tree_->children_.at(
id)) {
659 AddDescendantsDfsDepth(id_child, max_depth,
depth + 1);
663 void AddDescendantsBfs(
const Key&
id,
size_t max_depth) {
664 std::queue<std::pair<size_t, Key>> bfs;
666 while (!bfs.empty()) {
667 const size_t depth = bfs.front().first;
668 const Key& id_current = bfs.front().second;
669 ids_.push_back(id_current);
671 if (
depth >= max_depth)
continue;
672 for (
const Key& id_child : tree_->children_.at(id_current)) {
673 bfs.emplace(
depth + 1, id_child);
679 std::vector<Key> ids_;
682 template <
typename Key,
typename T>
683 template <
bool Const>
686 using TreeT = std::conditional_t<Const, const Tree<Key, T>,
Tree<Key, T>>;
691 : tree_(tree), ids_(&tree->children_.at(
id)) {}
698 const std::vector<Key>* ids_;
701 template <
typename Key,
typename T>
702 template <
bool Const>
705 using TreeT = std::conditional_t<Const, const Tree<Key, T>,
Tree<Key, T>>;
709 explicit RootView(TreeT* tree) : tree_(tree), ids_(FindRoots(tree)) {}
715 std::vector<Key> FindRoots(TreeT* tree) {
716 std::vector<Key>
roots;
717 for (
const auto& key_val : tree->nodes()) {
718 const Key& key = key_val.first;
719 if (!tree->parent(key))
roots.push_back(key);
725 std::vector<Key> ids_;
chain_view ancestors(const Key &id)
Definition: tree.h:129
void insert(const Key &id, const T &value)
Definition: tree.h:237
const T & at(const Key &id) const
Definition: tree.h:106
std::unordered_map< Key, std::optional< Key > > parents_
Definition: tree.h:455
const_descendant_view descendants(const Key &id, SearchType search_type=SearchType::kBreadthFirstSearch, size_t max_depth=std::numeric_limits< size_t >::max()) const
Definition: tree.h:178
void clear_children(const Key &id)
Definition: tree.h:354
size_t depth(const Key &id) const
Definition: tree.h:227
void printf(std::ostream &os, const std::function< std::string(const Key &key, const T &val)> &StringifyValue) const
Definition: tree.h:418
child_view children(const Key &id)
Definition: tree.h:323
void set_parent(const Key &id, const Key &id_parent)
Definition: tree.h:369
void insert(const Key &id, T &&value)
Definition: tree.h:251
void insert_child(const Key &id_parent, const Key &id, const T &value)
Definition: tree.h:267
bool contains(const Key &id) const
Definition: tree.h:217
descendant_view nodes(SearchType search_type, size_t max_depth=std::numeric_limits< size_t >::max())
Definition: tree.h:192
const std::optional< Key > & parent(const Key &id) const
Definition: tree.h:298
descendant_view descendants(const Key &id, SearchType search_type=SearchType::kBreadthFirstSearch, size_t max_depth=std::numeric_limits< size_t >::max())
Definition: tree.h:166
bool is_ancestor(const Key &id_ancestor, const Key &id) const
Definition: tree.h:394
bool empty() const
Definition: tree.h:80
std::unordered_map< Key, std::vector< Key > > children_
Definition: tree.h:460
size_t size() const
Definition: tree.h:85
const std::unordered_map< Key, T > & nodes() const
Definition: tree.h:90
void insert_child(const Key &id_parent, const Key &id, T &&value)
Definition: tree.h:282
std::unordered_map< Key, T > nodes_
Definition: tree.h:450
const_descendant_view nodes(SearchType search_type, size_t max_depth=std::numeric_limits< size_t >::max()) const
Definition: tree.h:206
void clear_parent(const Key &id)
Definition: tree.h:334
friend std::ostream & operator<<(std::ostream &os, const Tree< Key, T > &tree)
Definition: tree.h:434
void add_child(const Key &id, const Key &id_child)
Definition: tree.h:383
const_root_view roots() const
Definition: tree.h:98
const_chain_view ancestors(const Key &id) const
Definition: tree.h:137
bool is_descendant(const Key &id_descendant, const Key &id) const
Definition: tree.h:408
Definition: ctrl_utils.cc:18