Nvwa  1.1
tree.h
Go to the documentation of this file.
1 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
2 // vim:tabstop=4:shiftwidth=4:expandtab:
3 
4 /*
5  * Copyright (C) 2017 Wu Yongwei <wuyongwei at gmail dot com>
6  *
7  * This software is provided 'as-is', without any express or implied
8  * warranty. In no event will the authors be held liable for any
9  * damages arising from the use of this software.
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute
13  * it freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must
16  * not claim that you wrote the original software. If you use this
17  * software in a product, an acknowledgement in the product
18  * documentation would be appreciated but is not required.
19  * 2. Altered source versions must be plainly marked as such, and must
20  * not be misrepresented as being the original software.
21  * 3. This notice may not be removed or altered from any source
22  * distribution.
23  *
24  * This file is part of Stones of Nvwa:
25  * http://sourceforge.net/projects/nvwa
26  *
27  */
28 
38 #ifndef NVWA_TREE_H
39 #define NVWA_TREE_H
40 
41 #include <assert.h> // assert
42 #include <iterator> // std::begin/end/make_move_iterator
43 #include <memory> // std::unique_ptr/shared_ptr
44 #include <stack> // std::stack
45 #include <tuple> // std::tuple/make_tuple
46 #include <type_traits> // std::decay
47 #include <utility> // std::declval/forward/move/pair/...
48 #include <vector> // std::vector
49 #include "_nvwa.h" // NVWA_NAMESPACE_*
50 
51 NVWA_NAMESPACE_BEGIN
52 
54 enum class storage_policy
55 {
56  unique,
57  shared,
58 };
59 
60 #ifndef NVWA_TREE_DEFAULT_STORAGE_POLICY
61 #define NVWA_TREE_DEFAULT_STORAGE_POLICY storage_policy::shared
62 #endif
63 
65 template <typename _Tp, storage_policy _Policy>
66 struct smart_ptr;
67 
69 template <typename _Tp>
71 {
72  typedef std::unique_ptr<_Tp> type;
73 };
74 
76 template <typename _Tp>
78 {
79  typedef std::shared_ptr<_Tp> type;
80 };
81 
85 template <typename _Tp,
86  storage_policy _Policy = NVWA_TREE_DEFAULT_STORAGE_POLICY>
87 class tree
88 {
89 public:
90  typedef _Tp value_type;
91  typedef typename smart_ptr<tree, _Policy>::type tree_ptr;
92  typedef std::vector<tree_ptr> children_type;
93  typedef typename children_type::iterator iterator;
94  typedef typename children_type::const_iterator const_iterator;
95 
96  tree() : _M_value(_Tp()) {}
97  template <typename _Up>
98  explicit tree(_Up&& value, children_type children = {})
99  : _M_value(std::forward<_Up>(value))
100  , _M_children(std::move(children))
101  {
102  }
103  _Tp& value() &
104  {
105  return _M_value;
106  }
107  const _Tp& value() const &
108  {
109  return _M_value;
110  }
111  _Tp&& value() &&
112  {
113  return std::move(_M_value);
114  }
115  tree_ptr& child(unsigned index)
116  {
117  return _M_children[index];
118  }
119  const tree_ptr& child(unsigned index) const
120  {
121  return _M_children[index];
122  }
123  void push_back(tree_ptr ptr)
124  {
125  _M_children.push_back(std::move(ptr));
126  }
127  void pop_back()
128  {
129  _M_children.pop_back();
130  }
131  iterator begin()
132  {
133  return _M_children.begin();
134  }
135  const_iterator begin() const
136  {
137  return _M_children.begin();
138  }
139  const_iterator cbegin() const
140  {
141  return _M_children.begin();
142  }
143  iterator end()
144  {
145  return _M_children.end();
146  }
147  const_iterator end() const
148  {
149  return _M_children.end();
150  }
151  const_iterator cend() const
152  {
153  return _M_children.end();
154  }
155  bool has_child() const
156  {
157  return !_M_children.empty();
158  }
159  template <typename... Args>
160  void set_children(Args&&... args)
161  {
162  // initializer_list cannot be used to initialize a list of
163  // unique_ptrs; thus this workaround
164  tree_ptr init[] = {std::forward<Args>(args)...};
165  children_type children(std::make_move_iterator(std::begin(init)),
166  std::make_move_iterator(std::end(init)));
167  _M_children.swap(children);
168  }
169 
170  template <typename... Args>
171  static children_type make_children(Args&&... args)
172  {
173  tree_ptr init[] = {std::forward<Args>(args)...};
174  children_type children(std::make_move_iterator(std::begin(init)),
175  std::make_move_iterator(std::end(init)));
176  return children;
177  }
178 
179  template <typename _Up>
180  static tree_ptr create(_Up&& value, children_type children)
181  {
182  return tree_ptr(new tree(std::forward<_Up>(value),
183  std::move(children)));
184  }
185 
186  static constexpr tree_ptr null()
187  {
188  return tree_ptr();
189  }
190 
191 private:
192  _Tp _M_value;
193  children_type _M_children;
194 };
195 
202 template <storage_policy _Policy = NVWA_TREE_DEFAULT_STORAGE_POLICY,
203  typename _Tp>
204 typename tree<typename std::decay<_Tp>::type, _Policy>::tree_ptr
205 create_tree(_Tp&& value)
206 {
207  return tree<typename std::decay<_Tp>::type, _Policy>::create(
208  std::forward<_Tp>(value), {});
209 }
210 
218 template <storage_policy _Policy = NVWA_TREE_DEFAULT_STORAGE_POLICY,
219  typename _Tp, typename... Args>
220 typename tree<typename std::decay<_Tp>::type, _Policy>::tree_ptr
221 create_tree(_Tp&& value, Args&&... args)
222 {
223  return tree<typename std::decay<_Tp>::type, _Policy>::create(
224  std::forward<_Tp>(value),
225  tree<_Tp, _Policy>::make_children(std::forward<Args>(args)...));
226 }
227 
233 template <typename _Tree>
235 {
236 public:
237  class iterator
238  {
239  public:
240  typedef int difference_type;
241  typedef _Tree value_type;
242  typedef _Tree* pointer_type;
243  typedef _Tree& reference;
244  typedef std::forward_iterator_tag iterator_category;
245 
246  iterator() {}
247  iterator(pointer_type root)
248  : _M_this_level({root})
249  {
250  _M_current = _M_this_level.begin();
251  }
252 
253  reference operator*() const
254  {
255  assert(!empty());
256  return **_M_current;
257  }
258  pointer_type operator->() const
259  {
260  assert(!empty());
261  return &*_M_current;
262  }
263  iterator& operator++()
264  {
265  assert(!empty());
266  for (auto& child : **_M_current)
267  {
268  if (child != _Tree::null())
269  _M_next_level.push_back(&*child);
270  }
271  if (++_M_current == _M_this_level.end())
272  {
273  _M_this_level = std::move(_M_next_level);
274  _M_current = _M_this_level.begin();
275  }
276  return *this;
277  }
278  iterator operator++(int)
279  {
280  iterator temp(*this);
281  ++*this;
282  return temp;
283  }
284  bool empty() const
285  {
286  return _M_current == _M_this_level.end();
287  }
288  bool operator==(const iterator& rhs) const
289  {
290  return (empty() && rhs.empty()) || _M_current == rhs._M_current;
291  }
292  bool operator!=(const iterator& rhs) const
293  {
294  return !operator==(rhs);
295  }
296 
297  private:
298  typename std::vector<pointer_type>::iterator _M_current;
299  std::vector<pointer_type> _M_this_level;
300  std::vector<pointer_type> _M_next_level;
301  };
302 
303  breadth_first_iteration(_Tree& root)
304  : _M_root(&root)
305  {
306  }
307  iterator begin()
308  {
309  return iterator(_M_root);
310  }
311  iterator end()
312  {
313  return iterator();
314  }
315 
316 private:
317  _Tree* _M_root;
318 };
319 
325 template <typename _Tree>
327 {
328 public:
329  class iterator
330  {
331  public:
332  typedef int difference_type;
333  typedef _Tree value_type;
334  typedef _Tree* pointer_type;
335  typedef _Tree& reference;
336  typedef std::forward_iterator_tag iterator_category;
337 
338  iterator() : _M_current(nullptr) {}
339  iterator(pointer_type root) : _M_current(root) {}
340 
341  reference operator*() const
342  {
343  assert(!empty());
344  return *_M_current;
345  }
346  pointer_type operator->() const
347  {
348  assert(!empty());
349  return _M_current;
350  }
351  iterator& operator++()
352  {
353  assert(!empty());
354  _M_stack.push(
355  std::make_pair(_M_current->cbegin(), _M_current->cend()));
356  for (;;)
357  {
358  if (_M_stack.empty())
359  {
360  _M_current = nullptr;
361  break;
362  }
363  auto& top = _M_stack.top();
364  auto& next = top.first;
365  auto& end = top.second;
366  if (next != end)
367  {
368  _M_current = &**next++;
369  if (_M_current != nullptr)
370  break;
371  }
372  else
373  _M_stack.pop();
374  }
375  return *this;
376  }
377  iterator operator++(int)
378  {
379  iterator temp(*this);
380  ++*this;
381  return temp;
382  }
383  bool empty() const
384  {
385  return _M_current == nullptr;
386  }
387  bool operator==(const iterator& rhs) const
388  {
389  return (empty() && rhs.empty()) || _M_current == rhs._M_current;
390  }
391  bool operator!=(const iterator& rhs) const
392  {
393  return !operator==(rhs);
394  }
395 
396  private:
397  pointer_type _M_current;
398  std::stack<std::pair<typename _Tree::const_iterator,
399  typename _Tree::const_iterator>>
400  _M_stack;
401  };
402 
403  depth_first_iteration(_Tree& root)
404  : _M_root(&root)
405  {
406  }
407  iterator begin()
408  {
409  return iterator(_M_root);
410  }
411  iterator end()
412  {
413  return iterator();
414  }
415 
416 private:
417  _Tree* _M_root;
418 };
419 
425 template <typename _Tree>
427 {
428 public:
429  class iterator
430  {
431  public:
432  typedef int difference_type;
433  typedef _Tree value_type;
434  typedef _Tree* pointer_type;
435  typedef _Tree& reference;
436  typedef std::forward_iterator_tag iterator_category;
437 
438  iterator() : _M_current(nullptr) {}
439  iterator(pointer_type root)
440  {
441  _M_current = find_leftmost_child(root);
442  }
443 
444  reference operator*() const
445  {
446  assert(!empty());
447  return *_M_current;
448  }
449  pointer_type operator->() const
450  {
451  assert(!empty());
452  return _M_current;
453  }
454  iterator& operator++()
455  {
456  assert(!empty());
457  for (;;)
458  {
459  if (_M_stack.empty())
460  {
461  _M_current = nullptr;
462  break;
463  }
464  auto& top = _M_stack.top();
465  auto& node = std::get<0>(top);
466  auto& next = std::get<1>(top);
467  auto& end = std::get<2>(top);
468  if (node != nullptr)
469  {
470  _M_current = node;
471  node = nullptr; // Mark as traversed
472  break;
473  }
474  else
475  {
476  // Iterate over non-leftmost children
477  while (next != end)
478  {
479  auto it = next++;
480  if (*it)
481  {
482  _M_current = find_leftmost_child(&**it);
483  return *this;
484  }
485  }
486  _M_stack.pop();
487  }
488  }
489  return *this;
490  }
491  iterator operator++(int)
492  {
493  iterator temp(*this);
494  ++*this;
495  return temp;
496  }
497  bool empty() const
498  {
499  return _M_current == nullptr;
500  }
501  bool operator==(const iterator& rhs) const
502  {
503  return (empty() && rhs.empty()) || _M_current == rhs._M_current;
504  }
505  bool operator!=(const iterator& rhs) const
506  {
507  return !operator==(rhs);
508  }
509 
510  private:
511  pointer_type find_leftmost_child(pointer_type root)
512  {
513  using std::make_tuple;
514  auto curr = root;
515  for (;;)
516  {
517  if (!curr->has_child())
518  break;
519  auto left_child = curr->cbegin();
520  auto next_child = left_child;
521  if (next_child != curr->cend())
522  ++next_child;
523  if (*left_child)
524  {
525  _M_stack.push(
526  make_tuple(curr, next_child, curr->cend()));
527  curr = &**left_child;
528  }
529  else
530  {
531  _M_stack.push(
532  make_tuple(nullptr, next_child, curr->cend()));
533  break;
534  }
535  }
536  return curr;
537  }
538 
539  pointer_type _M_current;
540  std::stack<std::tuple<pointer_type,
541  typename _Tree::const_iterator,
542  typename _Tree::const_iterator>>
543  _M_stack;
544  };
545 
546  in_order_iteration(_Tree& root)
547  : _M_root(&root)
548  {
549  }
550  iterator begin()
551  {
552  return iterator(_M_root);
553  }
554  iterator end()
555  {
556  return iterator();
557  }
558 
559 private:
560  _Tree* _M_root;
561 };
562 
563 template <typename _Tree>
564 breadth_first_iteration<_Tree> traverse_breadth_first(_Tree& root)
565 {
566  return breadth_first_iteration<_Tree>(root);
567 }
568 
569 template <typename _Tree>
570 depth_first_iteration<_Tree> traverse_depth_first(_Tree& root)
571 {
572  return depth_first_iteration<_Tree>(root);
573 }
574 
575 template <typename _Tree>
576 in_order_iteration<_Tree> traverse_in_order(_Tree& root)
577 {
578  return in_order_iteration<_Tree>(root);
579 }
580 
581 NVWA_NAMESPACE_END
582 
583 #endif // NVWA_TREE_H
Members are directly owned.
Declaration of policy class to generate the smart pointer type.
Definition: tree.h:66
Iteration class for breadth-first traversal.
Definition: tree.h:234
Members may be shared and passed around.
tree< typename std::decay< _Tp >::type, _Policy >::tree_ptr create_tree(_Tp &&value, Args &&... args)
Creates a tree with children.
Definition: tree.h:221
Basic tree (node) class template that owns all its children.
Definition: tree.h:87
Iteration class for in-order traversal.
Definition: tree.h:426
storage_policy
_Policy class for how to store members.
Definition: tree.h:54
Iteration class for depth-first traversal.
Definition: tree.h:326
Common definitions for preprocessing.