16#ifndef DIRECTEDGRAPH_H
17#define DIRECTEDGRAPH_H
21namespace open_cpp_utils
50 using node = uint32_t;
51 using node_queue = std::deque<node>;
54 using hierarchy = std::vector<director>;
55 using storage = std::vector<data_type>;
74 node parent, child, prev_sibling, next_sibling;
75 uint32_t flags, depth;
77 director() : parent(0), child(0), prev_sibling(0), next_sibling(0), flags(VALID) { }
90 directed_tree() : graph_{ director() }, data_{ data_type() }, freed_{ } { }
100 [[nodiscard]] node
parent(node
id)
const {
return graph_[id].parent; }
107 [[nodiscard]] node
first_child(node
id)
const {
return graph_[id].child; }
114 [[nodiscard]] node
prev_sibling(node
id)
const {
return graph_[id].prev_sibling; }
121 [[nodiscard]] node
next_sibling(node
id)
const {
return graph_[id].next_sibling; }
140 [[nodiscard]] uint32_t
depth(node
id)
const
160 node
insert(
const data_type& data, node p_id)
164 freed_.push_back(
static_cast<node
>(graph_.size()));
165 graph_.push_back(director()); data_.push_back(data);
168 node
id = freed_.front(); freed_.pop_front();
169 director& node = graph_[id];
170 director&
parent = graph_[p_id];
175 director& nchild = graph_[
parent.child];
176 node.prev_sibling = nchild.prev_sibling;
177 nchild.prev_sibling = id;
179 if(nchild.prev_sibling)
181 director& pchild = graph_[nchild.prev_sibling];
182 pchild.next_sibling = id;
188 node.next_sibling =
parent.child;
190 node.flags = director::VALID;
209 director& erased = graph_[id];
210 erased.Flags &= ~director::VALID;
211 freed_.push_back(
id);
213 graph_[erased.parent].Child = erased.Sibling;
215 node_queue stack{ erased.Child };
217 while(stack.empty() ==
false)
219 node next = stack.front(); stack.pop_front();
220 director& child = graph_[next];
221 child.Flags &= ~director::VALID;
222 freed_.push_back(next);
224 if(child.Sibling) stack.push_front(child.Sibling);
225 if(child.Child) stack.push_front(child.Child);
244 [[nodiscard]]
const data_type&
operator[](node
id)
const {
return data_[id]; }
255 template<
typename O = pre_order,
typename V>
283 node operator()(node node)
285 node = visit_queue_.back(); visit_queue_.pop_back();
286 director& current = graph_.graph_[node];
288 if(current.next_sibling) visit_queue_.push_back(current.next_sibling);
289 if(current.child) visit_queue_.push_front(current.child);
291 if(visit_queue_.empty())
return 0;
297 node_queue visit_queue_;
309 node operator()(node
id)
311 director& current = graph_.graph_[id];
313 if(current.next_sibling) visit_queue_.push_front(current.next_sibling);
314 if(current.child) visit_queue_.push_front(current.child);
316 if(visit_queue_.empty())
return 0;
317 node next = visit_queue_.front(); visit_queue_.pop_front();
323 node_queue visit_queue_;
335 node operator()(node node)
337 if(node == 0) visit_queue_.push_back(graph_.left_most(node));
339 node = visit_queue_.front(); visit_queue_.pop_front();
340 director& current = graph_.graph_[node];
344 if(graph_.next_sibling(current.Sibling)) visit_queue_.push_back(current.parent);
345 visit_queue_.push_back(graph_.left_most(current.Sibling));
353 node_queue visit_queue_;
365 node operator()(node node)
367 if(visit_queue_.empty()) visit_queue_.push_back(graph_.left_most(node));
369 node = visit_queue_.front(); visit_queue_.pop_front();
370 if(node == 0)
return node;
371 director& current = graph_.graph_[node];
373 visit_queue_.push_back(current.Sibling ? graph_.left_most(current.Sibling) : graph_.parent(node));
380 node_queue visit_queue_;
387 template<
typename V,
typename O>
391 using visitor_type = V;
392 using order_type = O;
394 traverser(
directed_tree& graph, visitor_type& visitor) : graph_(graph), visitor_(visitor), order_(graph) { }
399 while(node = order_(node))
401 if(visitor_(graph_[node], node))
break;
407 visitor_type& visitor_;
Breadth first traversal.
Definition directed_tree.h:279
In-order traversal.
Definition directed_tree.h:331
Post-order traversal.
Definition directed_tree.h:361
Pre-order traversal.
Definition directed_tree.h:305
Visitor pattern for traversing the tree.
Definition directed_tree.h:389
Class for creating a directed tree.
Definition directed_tree.h:33
void erase(node id)
Erase a node in the tree.
Definition directed_tree.h:205
node insert(const data_type &data, node p_id)
Insert a node into the tree as a child of the provided node.
Definition directed_tree.h:160
directed_tree()
Default constructor, creates tree with empty root.
Definition directed_tree.h:90
node prev_sibling(node id) const
Get the previous sibling of a node. O(1)
Definition directed_tree.h:114
node next_sibling(node id) const
Get the next sibling of a node. O(1)
Definition directed_tree.h:121
node parent(node id) const
Get the parent of a node. O(1)
Definition directed_tree.h:100
node first_child(node id) const
Get the first child of a node. O(1)
Definition directed_tree.h:107
node left_most(node id) const
Get the left most child of a node. O(log(n))
Definition directed_tree.h:128
uint32_t depth(node id) const
Get the depth of a node.
Definition directed_tree.h:140
void traverse(V &visitor)
Traverser-Visitor pattern for accessing the tree.
Definition directed_tree.h:256
const data_type & operator[](node id) const
Constant getter for data associated with a node.
Definition directed_tree.h:244
data_type & operator[](node id)
Getter for data associated with a node.
Definition directed_tree.h:237
Compile-time constant value.
Definition template_utils.h:34
Provides compile time evaluation utilities for templates and template packs.