mdds
flat_segment_tree.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 // SPDX-FileCopyrightText: 2008 - 2025 Kohei Yoshida
4 //
5 // SPDX-License-Identifier: MIT
6 
7 #pragma once
8 
9 #include <iostream>
10 #include <sstream>
11 #include <utility>
12 #include <cassert>
13 #include <type_traits>
14 
15 #include "./node.hpp"
16 #include "./flat_segment_tree_itr.hpp"
17 #include "./global.hpp"
18 
19 #ifdef MDDS_UNIT_TEST
20 #include <cstdio>
21 #include <vector>
22 #endif
23 
24 namespace mdds {
25 
26 template<typename Key, typename Value>
28 {
29 public:
30  typedef Key key_type;
31  typedef Value value_type;
32  typedef size_t size_type;
33 
35  {
36  bool operator==(const nonleaf_value_type&) const noexcept
37  {
38  return true;
39  }
40  };
41 
43  {
44  value_type value;
45 
46  bool operator==(const leaf_value_type& r) const
47  noexcept(noexcept(std::declval<value_type>() == std::declval<value_type>()))
48  {
49  return value == r.value;
50  }
51 
52  bool operator!=(const leaf_value_type& r) const noexcept(noexcept(!operator==(r)))
53  {
54  return !operator==(r);
55  }
56 
57  leaf_value_type() : value{}
58  {}
59  };
60 
62  using node_ptr = typename node::node_ptr;
64 
65 private:
66  friend struct ::mdds::fst::detail::forward_itr_handler<flat_segment_tree>;
67  friend struct ::mdds::fst::detail::reverse_itr_handler<flat_segment_tree>;
68 
69  static constexpr bool nothrow_move_constructible_v =
70  std::is_nothrow_move_constructible_v<std::vector<nonleaf_node>> &&
71  std::is_nothrow_move_constructible_v<value_type>;
72 
73  static constexpr bool nothrow_swappable_v =
74  std::is_nothrow_swappable_v<value_type> && std::is_nothrow_swappable_v<std::vector<nonleaf_node>>;
75 
76  static constexpr bool nothrow_move_assignable_v = nothrow_move_constructible_v && nothrow_swappable_v;
77 
78  static constexpr bool nothrow_eq_comparable_v =
79  noexcept(std::declval<key_type>() == std::declval<key_type>()) &&
80  noexcept(std::declval<leaf_value_type>() == std::declval<leaf_value_type>());
81 
82 public:
84 
86  flat_segment_tree, ::mdds::fst::detail::forward_itr_handler<flat_segment_tree>>
87  {
88  typedef ::mdds::fst::detail::const_iterator_base<
90  base_type;
91  friend class flat_segment_tree;
92 
93  using base_type::get_parent;
94  using base_type::get_pos;
95  using base_type::is_end_pos;
96 
97  public:
98  const_iterator() : base_type(nullptr, false)
99  {}
100 
106 
107  private:
108  explicit const_iterator(const typename base_type::fst_type* _db, bool _end) : base_type(_db, _end)
109  {}
110 
111  explicit const_iterator(const typename base_type::fst_type* _db, const node* p) : base_type(_db, p)
112  {}
113  };
114 
116  flat_segment_tree, ::mdds::fst::detail::reverse_itr_handler<flat_segment_tree>>
117  {
118  typedef ::mdds::fst::detail::const_iterator_base<
120  base_type;
121  friend class flat_segment_tree;
122 
123  public:
124  const_reverse_iterator() : base_type(nullptr, false)
125  {}
126 
127  private:
128  explicit const_reverse_iterator(const typename base_type::fst_type* _db, bool _end) : base_type(_db, _end)
129  {}
130  };
131 
133  {
134  node_ptr m_left_leaf;
135  node_ptr m_right_leaf;
136 
137  public:
138  const_segment_range_type(node_ptr left_leaf, node_ptr right_leaf);
139 
140  const_segment_iterator begin() const;
141  const_segment_iterator end() const;
142  };
143 
152  {
153  return const_iterator(this, false);
154  }
155 
165  {
166  return const_iterator(this, true);
167  }
168 
178  {
179  return const_reverse_iterator(this, false);
180  }
181 
192  {
193  return const_reverse_iterator(this, true);
194  }
195 
206  const_segment_iterator begin_segment() const;
207 
219  const_segment_iterator end_segment() const;
220 
224  const_segment_range_type segment_range() const;
225 
226  flat_segment_tree() = delete;
227 
239  flat_segment_tree(key_type min_val, key_type max_val, value_type init_val);
240 
245 
252  flat_segment_tree(flat_segment_tree&& other) noexcept(nothrow_move_constructible_v);
253 
255 
263  flat_segment_tree<Key, Value>& operator=(const flat_segment_tree& other);
264 
270  flat_segment_tree<Key, Value>& operator=(flat_segment_tree&& other) noexcept(nothrow_move_assignable_v);
271 
277  void swap(flat_segment_tree& other) noexcept(nothrow_swappable_v);
278 
284  void clear();
285 
300  std::pair<const_iterator, bool> insert_front(key_type start_key, key_type end_key, value_type val)
301  {
302  return insert_segment_impl(std::move(start_key), std::move(end_key), std::move(val), true);
303  }
304 
320  std::pair<const_iterator, bool> insert_back(key_type start_key, key_type end_key, value_type val)
321  {
322  return insert_segment_impl(std::move(start_key), std::move(end_key), std::move(val), false);
323  }
324 
340  std::pair<const_iterator, bool> insert(const_iterator pos, key_type start_key, key_type end_key, value_type val);
341 
351  void shift_left(key_type start_key, key_type end_key);
352 
365  void shift_right(key_type pos, key_type size, bool skip_start_node);
366 
384  std::pair<const_iterator, bool> search(
385  key_type key, value_type& value, key_type* start_key = nullptr, key_type* end_key = nullptr) const;
386 
405  std::pair<const_iterator, bool> search(
406  const_iterator pos, key_type key, value_type& value, key_type* start_key = nullptr,
407  key_type* end_key = nullptr) const;
408 
418  const_iterator search(key_type key) const;
419 
432  const_iterator search(const_iterator pos, key_type key) const;
433 
453  std::pair<const_iterator, bool> search_tree(
454  key_type key, value_type& value, key_type* start_key = nullptr, key_type* end_key = nullptr) const;
455 
466  const_iterator search_tree(key_type key) const;
467 
473  void build_tree();
474 
479  bool valid_tree() const noexcept
480  {
481  return m_valid_tree;
482  }
483 
490  [[deprecated("Use valid_tree() instead")]]
491  bool is_tree_valid() const noexcept
492  {
493  return m_valid_tree;
494  }
495 
501  bool operator==(const flat_segment_tree& other) const noexcept(nothrow_eq_comparable_v);
502 
503  bool operator!=(const flat_segment_tree& other) const noexcept(nothrow_eq_comparable_v)
504  {
505  return !operator==(other);
506  }
507 
508  const key_type& min_key() const noexcept
509  {
510  return m_left_leaf->key;
511  }
512 
513  const key_type& max_key() const noexcept
514  {
515  return m_right_leaf->key;
516  }
517 
518  const value_type& default_value() const noexcept
519  {
520  return m_init_val;
521  }
522 
528  size_type leaf_size() const
529  noexcept(noexcept(st::detail::count_leaf_nodes<size_type>(m_left_leaf.get(), m_right_leaf.get())))
530  {
531  return st::detail::count_leaf_nodes<size_type>(m_left_leaf.get(), m_right_leaf.get());
532  }
533 
534 #ifdef MDDS_UNIT_TEST
535  const nonleaf_node* get_root_node() const
536  {
537  return m_root_node;
538  }
539 
540  struct tree_dumper_traits
541  {
542  using leaf_type = node;
543  using nonleaf_type = nonleaf_node;
544  using tree_type = flat_segment_tree;
545 
546  struct to_string
547  {
548  to_string(const tree_type&)
549  {}
550 
551  std::string operator()(const leaf_type& leaf) const
552  {
553  return leaf.to_string();
554  }
555 
556  std::string operator()(const nonleaf_type& nonleaf) const
557  {
558  return nonleaf.to_string();
559  }
560  };
561  };
562 
563  void dump_tree() const
564  {
565  using ::std::cout;
566  using ::std::endl;
567 
568  if (!m_valid_tree)
569  assert(!"attempted to dump an invalid tree!");
570 
571  size_t node_count = mdds::st::detail::tree_dumper<tree_dumper_traits>::dump(std::cout, *this, m_root_node);
572  size_t node_instance_count = node::get_instance_count();
573  size_t leaf_count = leaf_size();
574 
575  cout << "tree node count = " << node_count << "; node instance count = " << node_instance_count
576  << "; leaf node count = " << leaf_count << endl;
577 
578  assert(leaf_count == node_instance_count);
579  }
580 
581  void dump_leaf_nodes() const
582  {
583  using ::std::cout;
584  using ::std::endl;
585 
586  cout << "------------------------------------------" << endl;
587 
588  node_ptr cur_node = m_left_leaf;
589  long node_id = 0;
590  while (cur_node)
591  {
592  cout << " node " << node_id++ << ": key = " << cur_node->key << "; value = " << cur_node->value_leaf.value
593  << endl;
594  cur_node = cur_node->next;
595  }
596  cout << endl << " node instance count = " << node::get_instance_count() << endl;
597  }
598 
606  bool verify_keys(const ::std::vector<key_type>& key_values) const
607  {
608  {
609  // Start from the left-most node, and traverse right.
610  node* cur_node = m_left_leaf.get();
611  typename ::std::vector<key_type>::const_iterator itr = key_values.begin(), itr_end = key_values.end();
612  for (; itr != itr_end; ++itr)
613  {
614  if (!cur_node)
615  // Position past the right-mode node. Invalid.
616  return false;
617 
618  if (cur_node->key != *itr)
619  // Key values differ.
620  return false;
621 
622  cur_node = cur_node->next.get();
623  }
624 
625  if (cur_node)
626  // At this point, we expect the current node to be at the position
627  // past the right-most node, which is nullptr.
628  return false;
629  }
630 
631  {
632  // Start from the right-most node, and traverse left.
633  node* cur_node = m_right_leaf.get();
634  typename ::std::vector<key_type>::const_reverse_iterator itr = key_values.rbegin(),
635  itr_end = key_values.rend();
636  for (; itr != itr_end; ++itr)
637  {
638  if (!cur_node)
639  // Position past the left-mode node. Invalid.
640  return false;
641 
642  if (cur_node->key != *itr)
643  // Key values differ.
644  return false;
645 
646  cur_node = cur_node->prev.get();
647  }
648 
649  if (cur_node)
650  // Likewise, we expect the current position to be past the
651  // left-most node, in which case the node value is nullptr.
652  return false;
653  }
654 
655  return true;
656  }
657 
665  bool verify_values(const ::std::vector<value_type>& values) const
666  {
667  node* cur_node = m_left_leaf.get();
668  node* end_node = m_right_leaf.get();
669  typename ::std::vector<value_type>::const_iterator itr = values.begin(), itr_end = values.end();
670  for (; itr != itr_end; ++itr)
671  {
672  if (cur_node == end_node || !cur_node)
673  return false;
674 
675  if (cur_node->value_leaf.value != *itr)
676  // Key values differ.
677  return false;
678 
679  cur_node = cur_node->next.get();
680  }
681 
682  if (cur_node != end_node)
683  // At this point, we expect the current node to be at the end of
684  // range.
685  return false;
686 
687  return true;
688  }
689 #endif
690 
691 private:
692  const_iterator search_by_key_impl(const node* start_pos, key_type key) const;
693 
694  const node* search_tree_for_leaf_node(key_type key) const;
695 
696  void append_new_segment(key_type start_key)
697  {
698  if (m_right_leaf->prev->key == start_key)
699  {
700  m_right_leaf->prev->value_leaf.value = m_init_val;
701  return;
702  }
703 
704 #ifdef MDDS_UNIT_TEST
705  // The start position must come after the position of the last node
706  // before the right-most node.
707  assert(m_right_leaf->prev->key < start_key);
708 #endif
709 
710  if (m_right_leaf->prev->value_leaf.value == m_init_val)
711  // The existing segment has the same value. No need to insert a
712  // new segment.
713  return;
714 
715  node_ptr new_node(new node);
716  new_node->key = start_key;
717  new_node->value_leaf.value = m_init_val;
718  new_node->prev = m_right_leaf->prev;
719  new_node->next = m_right_leaf;
720  m_right_leaf->prev->next = new_node;
721  m_right_leaf->prev = std::move(new_node);
722  m_valid_tree = false;
723  }
724 
725  ::std::pair<const_iterator, bool> insert_segment_impl(
726  key_type start_key, key_type end_key, value_type val, bool forward);
727 
728  ::std::pair<const_iterator, bool> insert_to_pos(
729  node_ptr start_pos, key_type start_key, key_type end_key, value_type val);
730 
731  ::std::pair<const_iterator, bool> search_impl(
732  const node* pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const;
733 
734  const node* get_insertion_pos_leaf_reverse(const key_type& key, const node* start_pos) const;
735 
746  const node* get_insertion_pos_leaf(const key_type& key, const node* start_pos) const;
747 
748  static void shift_leaf_key_left(node_ptr& begin_node, node_ptr& end_node, key_type shift_value)
749  {
750  node* cur_node_p = begin_node.get();
751  node* end_node_p = end_node.get();
752  while (cur_node_p != end_node_p)
753  {
754  cur_node_p->key -= shift_value;
755  cur_node_p = cur_node_p->next.get();
756  }
757  }
758 
759  static void shift_leaf_key_right(node_ptr& cur_node, node_ptr& end_node, key_type shift_value)
760  {
761  key_type end_node_key = end_node->key;
762  while (cur_node.get() != end_node.get())
763  {
764  cur_node->key += shift_value;
765  if (cur_node->key < end_node_key)
766  {
767  // The node is still in-bound. Keep shifting.
768  cur_node = cur_node->next;
769  continue;
770  }
771 
772  // This node has been pushed outside the end node position.
773  // Remove all nodes that follows, and connect the previous node
774  // with the end node.
775 
776  node_ptr last_node = cur_node->prev;
777  while (cur_node.get() != end_node.get())
778  {
779  node_ptr next_node = cur_node->next;
780  disconnect_all_nodes(cur_node.get());
781  cur_node = std::move(next_node);
782  }
783  last_node->next = end_node;
784  end_node->prev = std::move(last_node);
785  return;
786  }
787  }
788 
789  void destroy();
790 
798  bool adjust_segment_range(key_type& start_key, key_type& end_key) const;
799 
800 private:
801  std::vector<nonleaf_node> m_nonleaf_node_pool;
802 
803  const nonleaf_node* m_root_node;
804  node_ptr m_left_leaf;
805  node_ptr m_right_leaf;
806  value_type m_init_val;
807  bool m_valid_tree;
808 };
809 
810 template<typename Key, typename Value>
811 void swap(flat_segment_tree<Key, Value>& left, flat_segment_tree<Key, Value>& right) noexcept(
812  std::is_nothrow_swappable_v<flat_segment_tree<Key, Value>>)
813 {
814  left.swap(right);
815 }
816 
817 } // namespace mdds
818 
819 #include "flat_segment_tree_def.inl"
820 
821 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: flat_segment_tree.hpp:132
Definition: flat_segment_tree_itr.hpp:46
Definition: flat_segment_tree.hpp:115
bool valid_tree() const noexcept
Definition: flat_segment_tree.hpp:479
size_type leaf_size() const noexcept(noexcept(st::detail::count_leaf_nodes< size_type >(m_left_leaf.get(), m_right_leaf.get())))
Definition: flat_segment_tree.hpp:528
Definition: node.hpp:105
const_reverse_iterator rbegin() const
Definition: flat_segment_tree.hpp:177
const_segment_range_type segment_range() const
Definition: flat_segment_tree.hpp:42
const_segment_iterator end_segment() const
bool is_tree_valid() const noexcept
Definition: flat_segment_tree.hpp:491
const_reverse_iterator rend() const
Definition: flat_segment_tree.hpp:191
const_iterator end() const
Definition: flat_segment_tree.hpp:164
std::pair< const_iterator, bool > insert(const_iterator pos, key_type start_key, key_type end_key, value_type val)
std::pair< const_iterator, bool > insert_front(key_type start_key, key_type end_key, value_type val)
Definition: flat_segment_tree.hpp:300
std::pair< const_iterator, bool > search_tree(key_type key, value_type &value, key_type *start_key=nullptr, key_type *end_key=nullptr) const
Definition: node.hpp:418
Definition: flat_segment_tree_itr.hpp:73
Definition: flat_segment_tree_itr.hpp:16
const_segment_iterator begin_segment() const
Definition: flat_segment_tree_itr.hpp:170
void shift_right(key_type pos, key_type size, bool skip_start_node)
Definition: flat_segment_tree.hpp:27
Definition: cref_wrapper.hpp:12
bool operator==(const flat_segment_tree &other) const noexcept(nothrow_eq_comparable_v)
Definition: flat_segment_tree.hpp:34
std::pair< const_iterator, bool > insert_back(key_type start_key, key_type end_key, value_type val)
Definition: flat_segment_tree.hpp:320
std::pair< const_iterator, bool > search(key_type key, value_type &value, key_type *start_key=nullptr, key_type *end_key=nullptr) const
void shift_left(key_type start_key, key_type end_key)
Definition: flat_segment_tree.hpp:85
void swap(flat_segment_tree &other) noexcept(nothrow_swappable_v)
const_segment_iterator to_segment() const
const_iterator begin() const
Definition: flat_segment_tree.hpp:151
Definition: node.hpp:39