mdds
flat_segment_tree.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * Copyright (c) 2008-2023 Kohei Yoshida
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  ************************************************************************/
28 
29 #ifndef INCLUDED_MDDS_FLAT_SEGMENT_TREE_HPP
30 #define INCLUDED_MDDS_FLAT_SEGMENT_TREE_HPP
31 
32 #include <iostream>
33 #include <sstream>
34 #include <utility>
35 #include <cassert>
36 
37 #include "mdds/node.hpp"
38 #include "mdds/flat_segment_tree_itr.hpp"
39 #include "mdds/global.hpp"
40 
41 #ifdef MDDS_UNIT_TEST
42 #include <cstdio>
43 #include <vector>
44 #endif
45 
46 namespace mdds {
47 
48 template<typename Key, typename Value>
50 {
51 public:
52  typedef Key key_type;
53  typedef Value value_type;
54  typedef size_t size_type;
55 
57  {
58  };
59 
61  {
62  value_type value;
63 
64  bool operator==(const leaf_value_type& r) const
65  {
66  return value == r.value;
67  }
68 
69  bool operator!=(const leaf_value_type& r) const
70  {
71  return !operator==(r);
72  }
73 
74  leaf_value_type() : value{}
75  {}
76  };
77 
79  using node_ptr = typename node::node_ptr;
81 
82 private:
83  friend struct ::mdds::fst::detail::forward_itr_handler<flat_segment_tree>;
84  friend struct ::mdds::fst::detail::reverse_itr_handler<flat_segment_tree>;
85 
86 public:
88 
90  flat_segment_tree, ::mdds::fst::detail::forward_itr_handler<flat_segment_tree>>
91  {
92  typedef ::mdds::fst::detail::const_iterator_base<
94  base_type;
95  friend class flat_segment_tree;
96 
97  using base_type::get_parent;
98  using base_type::get_pos;
99  using base_type::is_end_pos;
100 
101  public:
102  const_iterator() : base_type(nullptr, false)
103  {}
104 
110 
111  private:
112  explicit const_iterator(const typename base_type::fst_type* _db, bool _end) : base_type(_db, _end)
113  {}
114 
115  explicit const_iterator(const typename base_type::fst_type* _db, const node* p) : base_type(_db, p)
116  {}
117  };
118 
120  flat_segment_tree, ::mdds::fst::detail::reverse_itr_handler<flat_segment_tree>>
121  {
122  typedef ::mdds::fst::detail::const_iterator_base<
124  base_type;
125  friend class flat_segment_tree;
126 
127  public:
128  const_reverse_iterator() : base_type(nullptr, false)
129  {}
130 
131  private:
132  explicit const_reverse_iterator(const typename base_type::fst_type* _db, bool _end) : base_type(_db, _end)
133  {}
134  };
135 
137  {
138  node_ptr m_left_leaf;
139  node_ptr m_right_leaf;
140 
141  public:
142  const_segment_range_type(node_ptr left_leaf, node_ptr right_leaf);
143 
144  const_segment_iterator begin() const;
145  const_segment_iterator end() const;
146  };
147 
156  {
157  return const_iterator(this, false);
158  }
159 
169  {
170  return const_iterator(this, true);
171  }
172 
182  {
183  return const_reverse_iterator(this, false);
184  }
185 
196  {
197  return const_reverse_iterator(this, true);
198  }
199 
210  const_segment_iterator begin_segment() const;
211 
223  const_segment_iterator end_segment() const;
224 
228  const_segment_range_type segment_range() const;
229 
230  flat_segment_tree() = delete;
231 
243  flat_segment_tree(key_type min_val, key_type max_val, value_type init_val);
244 
249 
257 
259 
268 
275 
281  void swap(flat_segment_tree& other);
282 
288  void clear();
289 
304  std::pair<const_iterator, bool> insert_front(key_type start_key, key_type end_key, value_type val)
305  {
306  return insert_segment_impl(std::move(start_key), std::move(end_key), std::move(val), true);
307  }
308 
324  std::pair<const_iterator, bool> insert_back(key_type start_key, key_type end_key, value_type val)
325  {
326  return insert_segment_impl(std::move(start_key), std::move(end_key), std::move(val), false);
327  }
328 
344  std::pair<const_iterator, bool> insert(
345  const const_iterator& pos, key_type start_key, key_type end_key, value_type val);
346 
356  void shift_left(key_type start_key, key_type end_key);
357 
370  void shift_right(key_type pos, key_type size, bool skip_start_node);
371 
389  std::pair<const_iterator, bool> search(
390  key_type key, value_type& value, key_type* start_key = nullptr, key_type* end_key = nullptr) const;
391 
410  std::pair<const_iterator, bool> search(
411  const const_iterator& pos, key_type key, value_type& value, key_type* start_key = nullptr,
412  key_type* end_key = nullptr) const;
413 
423  const_iterator search(key_type key) const;
424 
437  const_iterator search(const const_iterator& pos, key_type key) const;
438 
458  std::pair<const_iterator, bool> search_tree(
459  key_type key, value_type& value, key_type* start_key = nullptr, key_type* end_key = nullptr) const;
460 
471  const_iterator search_tree(key_type key) const;
472 
478  void build_tree();
479 
484  bool valid_tree() const noexcept
485  {
486  return m_valid_tree;
487  }
488 
494  bool operator==(const flat_segment_tree& other) const;
495 
496  bool operator!=(const flat_segment_tree& other) const
497  {
498  return !operator==(other);
499  }
500 
501  key_type min_key() const
502  {
503  return m_left_leaf->key;
504  }
505 
506  key_type max_key() const
507  {
508  return m_right_leaf->key;
509  }
510 
511  value_type default_value() const
512  {
513  return m_init_val;
514  }
515 
521  size_type leaf_size() const;
522 
523 #ifdef MDDS_UNIT_TEST
524  const nonleaf_node* get_root_node() const
525  {
526  return m_root_node;
527  }
528 
529  struct tree_dumper_traits
530  {
531  using leaf_type = node;
532  using nonleaf_type = nonleaf_node;
533  using tree_type = flat_segment_tree;
534 
535  struct to_string
536  {
537  to_string(const tree_type&)
538  {}
539 
540  std::string operator()(const leaf_type& leaf) const
541  {
542  return leaf.to_string();
543  }
544 
545  std::string operator()(const nonleaf_type& nonleaf) const
546  {
547  return nonleaf.to_string();
548  }
549  };
550  };
551 
552  void dump_tree() const
553  {
554  using ::std::cout;
555  using ::std::endl;
556 
557  if (!m_valid_tree)
558  assert(!"attempted to dump an invalid tree!");
559 
560  size_t node_count = mdds::st::detail::tree_dumper<tree_dumper_traits>::dump(std::cout, *this, m_root_node);
561  size_t node_instance_count = node::get_instance_count();
562  size_t leaf_count = leaf_size();
563 
564  cout << "tree node count = " << node_count << "; node instance count = " << node_instance_count
565  << "; leaf node count = " << leaf_count << endl;
566 
567  assert(leaf_count == node_instance_count);
568  }
569 
570  void dump_leaf_nodes() const
571  {
572  using ::std::cout;
573  using ::std::endl;
574 
575  cout << "------------------------------------------" << endl;
576 
577  node_ptr cur_node = m_left_leaf;
578  long node_id = 0;
579  while (cur_node)
580  {
581  cout << " node " << node_id++ << ": key = " << cur_node->key << "; value = " << cur_node->value_leaf.value
582  << endl;
583  cur_node = cur_node->next;
584  }
585  cout << endl << " node instance count = " << node::get_instance_count() << endl;
586  }
587 
595  bool verify_keys(const ::std::vector<key_type>& key_values) const
596  {
597  {
598  // Start from the left-most node, and traverse right.
599  node* cur_node = m_left_leaf.get();
600  typename ::std::vector<key_type>::const_iterator itr = key_values.begin(), itr_end = key_values.end();
601  for (; itr != itr_end; ++itr)
602  {
603  if (!cur_node)
604  // Position past the right-mode node. Invalid.
605  return false;
606 
607  if (cur_node->key != *itr)
608  // Key values differ.
609  return false;
610 
611  cur_node = cur_node->next.get();
612  }
613 
614  if (cur_node)
615  // At this point, we expect the current node to be at the position
616  // past the right-most node, which is nullptr.
617  return false;
618  }
619 
620  {
621  // Start from the right-most node, and traverse left.
622  node* cur_node = m_right_leaf.get();
623  typename ::std::vector<key_type>::const_reverse_iterator itr = key_values.rbegin(),
624  itr_end = key_values.rend();
625  for (; itr != itr_end; ++itr)
626  {
627  if (!cur_node)
628  // Position past the left-mode node. Invalid.
629  return false;
630 
631  if (cur_node->key != *itr)
632  // Key values differ.
633  return false;
634 
635  cur_node = cur_node->prev.get();
636  }
637 
638  if (cur_node)
639  // Likewise, we expect the current position to be past the
640  // left-most node, in which case the node value is nullptr.
641  return false;
642  }
643 
644  return true;
645  }
646 
654  bool verify_values(const ::std::vector<value_type>& values) const
655  {
656  node* cur_node = m_left_leaf.get();
657  node* end_node = m_right_leaf.get();
658  typename ::std::vector<value_type>::const_iterator itr = values.begin(), itr_end = values.end();
659  for (; itr != itr_end; ++itr)
660  {
661  if (cur_node == end_node || !cur_node)
662  return false;
663 
664  if (cur_node->value_leaf.value != *itr)
665  // Key values differ.
666  return false;
667 
668  cur_node = cur_node->next.get();
669  }
670 
671  if (cur_node != end_node)
672  // At this point, we expect the current node to be at the end of
673  // range.
674  return false;
675 
676  return true;
677  }
678 #endif
679 
680 private:
681  const_iterator search_by_key_impl(const node* start_pos, key_type key) const;
682 
683  const node* search_tree_for_leaf_node(key_type key) const;
684 
685  void append_new_segment(key_type start_key)
686  {
687  if (m_right_leaf->prev->key == start_key)
688  {
689  m_right_leaf->prev->value_leaf.value = m_init_val;
690  return;
691  }
692 
693 #ifdef MDDS_UNIT_TEST
694  // The start position must come after the position of the last node
695  // before the right-most node.
696  assert(m_right_leaf->prev->key < start_key);
697 #endif
698 
699  if (m_right_leaf->prev->value_leaf.value == m_init_val)
700  // The existing segment has the same value. No need to insert a
701  // new segment.
702  return;
703 
704  node_ptr new_node(new node);
705  new_node->key = start_key;
706  new_node->value_leaf.value = m_init_val;
707  new_node->prev = m_right_leaf->prev;
708  new_node->next = m_right_leaf;
709  m_right_leaf->prev->next = new_node;
710  m_right_leaf->prev = std::move(new_node);
711  m_valid_tree = false;
712  }
713 
714  ::std::pair<const_iterator, bool> insert_segment_impl(
715  key_type start_key, key_type end_key, value_type val, bool forward);
716 
717  ::std::pair<const_iterator, bool> insert_to_pos(
718  node_ptr start_pos, key_type start_key, key_type end_key, value_type val);
719 
720  ::std::pair<const_iterator, bool> search_impl(
721  const node* pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const;
722 
723  const node* get_insertion_pos_leaf_reverse(const key_type& key, const node* start_pos) const;
724 
735  const node* get_insertion_pos_leaf(const key_type& key, const node* start_pos) const;
736 
737  static void shift_leaf_key_left(node_ptr& begin_node, node_ptr& end_node, key_type shift_value)
738  {
739  node* cur_node_p = begin_node.get();
740  node* end_node_p = end_node.get();
741  while (cur_node_p != end_node_p)
742  {
743  cur_node_p->key -= shift_value;
744  cur_node_p = cur_node_p->next.get();
745  }
746  }
747 
748  static void shift_leaf_key_right(node_ptr& cur_node, node_ptr& end_node, key_type shift_value)
749  {
750  key_type end_node_key = end_node->key;
751  while (cur_node.get() != end_node.get())
752  {
753  cur_node->key += shift_value;
754  if (cur_node->key < end_node_key)
755  {
756  // The node is still in-bound. Keep shifting.
757  cur_node = cur_node->next;
758  continue;
759  }
760 
761  // This node has been pushed outside the end node position.
762  // Remove all nodes that follows, and connect the previous node
763  // with the end node.
764 
765  node_ptr last_node = cur_node->prev;
766  while (cur_node.get() != end_node.get())
767  {
768  node_ptr next_node = cur_node->next;
769  disconnect_all_nodes(cur_node.get());
770  cur_node = std::move(next_node);
771  }
772  last_node->next = end_node;
773  end_node->prev = std::move(last_node);
774  return;
775  }
776  }
777 
778  void destroy();
779 
787  bool adjust_segment_range(key_type& start_key, key_type& end_key) const;
788 
789 private:
790  std::vector<nonleaf_node> m_nonleaf_node_pool;
791 
792  const nonleaf_node* m_root_node;
793  node_ptr m_left_leaf;
794  node_ptr m_right_leaf;
795  value_type m_init_val;
796  bool m_valid_tree;
797 };
798 
799 template<typename Key, typename Value>
800 void swap(flat_segment_tree<Key, Value>& left, flat_segment_tree<Key, Value>& right)
801 {
802  left.swap(right);
803 }
804 
805 } // namespace mdds
806 
807 #include "flat_segment_tree_def.inl"
808 
809 #endif
810 
811 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: flat_segment_tree.hpp:136
Definition: flat_segment_tree_itr.hpp:67
Definition: flat_segment_tree.hpp:119
bool valid_tree() const noexcept
Definition: flat_segment_tree.hpp:484
Definition: node.hpp:122
const_reverse_iterator rbegin() const
Definition: flat_segment_tree.hpp:181
size_type leaf_size() const
const_segment_range_type segment_range() const
Definition: flat_segment_tree.hpp:60
const_segment_iterator end_segment() const
std::pair< const_iterator, bool > insert(const const_iterator &pos, key_type start_key, key_type end_key, value_type val)
bool operator==(const flat_segment_tree &other) const
const_reverse_iterator rend() const
Definition: flat_segment_tree.hpp:195
const_iterator end() const
Definition: flat_segment_tree.hpp:168
std::pair< const_iterator, bool > insert_front(key_type start_key, key_type end_key, value_type val)
Definition: flat_segment_tree.hpp:304
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:426
Definition: flat_segment_tree_itr.hpp:94
Definition: flat_segment_tree_itr.hpp:37
const_segment_iterator begin_segment() const
Definition: flat_segment_tree_itr.hpp:198
void shift_right(key_type pos, key_type size, bool skip_start_node)
Definition: flat_segment_tree.hpp:49
Definition: cref_wrapper.hpp:34
Definition: flat_segment_tree.hpp:56
flat_segment_tree< Key, Value > & operator=(const flat_segment_tree &other)
std::pair< const_iterator, bool > insert_back(key_type start_key, key_type end_key, value_type val)
Definition: flat_segment_tree.hpp:324
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:89
void swap(flat_segment_tree &other)
const_segment_iterator to_segment() const
const_iterator begin() const
Definition: flat_segment_tree.hpp:155
Definition: node.hpp:63