mdds
Loading...
Searching...
No Matches
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
24namespace mdds {
25
26template<typename Key, typename Value>
27class flat_segment_tree
28{
29public:
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
42 struct leaf_value_type
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
65private:
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
82public:
84
85 class const_iterator : public ::mdds::fst::detail::const_iterator_base<
86 flat_segment_tree, ::mdds::fst::detail::forward_itr_handler<flat_segment_tree>>
87 {
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
105 const_segment_iterator to_segment() const;
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
115 class const_reverse_iterator : public ::mdds::fst::detail::const_iterator_base<
116 flat_segment_tree, ::mdds::fst::detail::reverse_itr_handler<flat_segment_tree>>
117 {
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
132 class const_segment_range_type
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
225
226 flat_segment_tree() = delete;
227
239 flat_segment_tree(key_type min_val, key_type max_val, value_type init_val);
240
244 flat_segment_tree(const flat_segment_tree& r);
245
252 flat_segment_tree(flat_segment_tree&& other) noexcept(nothrow_move_constructible_v);
253
254 ~flat_segment_tree();
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
474
479 bool valid_tree() const noexcept
480 {
481 return m_valid_tree;
482 }
483
489 bool operator==(const flat_segment_tree& other) const noexcept(nothrow_eq_comparable_v);
490
491 bool operator!=(const flat_segment_tree& other) const noexcept(nothrow_eq_comparable_v)
492 {
493 return !operator==(other);
494 }
495
496 const key_type& min_key() const noexcept
497 {
498 return m_left_leaf->key;
499 }
500
501 const key_type& max_key() const noexcept
502 {
503 return m_right_leaf->key;
504 }
505
506 const value_type& default_value() const noexcept
507 {
508 return m_init_val;
509 }
510
516 size_type leaf_size() const
517 noexcept(noexcept(st::detail::count_leaf_nodes<size_type>(m_left_leaf.get(), m_right_leaf.get())))
518 {
519 return st::detail::count_leaf_nodes<size_type>(m_left_leaf.get(), m_right_leaf.get());
520 }
521
522#ifdef MDDS_UNIT_TEST
523 const nonleaf_node* get_root_node() const
524 {
525 return m_root_node;
526 }
527
528 struct tree_dumper_traits
529 {
530 using leaf_type = node;
531 using nonleaf_type = nonleaf_node;
532 using tree_type = flat_segment_tree;
533
534 struct to_string
535 {
536 to_string(const tree_type&)
537 {}
538
539 std::string operator()(const leaf_type& leaf) const
540 {
541 return leaf.to_string();
542 }
543
544 std::string operator()(const nonleaf_type& nonleaf) const
545 {
546 return nonleaf.to_string();
547 }
548 };
549 };
550
551 void dump_tree() const
552 {
553 using ::std::cout;
554 using ::std::endl;
555
556 if (!m_valid_tree)
557 assert(!"attempted to dump an invalid tree!");
558
559 size_t node_count = mdds::st::detail::tree_dumper<tree_dumper_traits>::dump(std::cout, *this, m_root_node);
560 size_t node_instance_count = node::get_instance_count();
561 size_t leaf_count = leaf_size();
562
563 cout << "tree node count = " << node_count << "; node instance count = " << node_instance_count
564 << "; leaf node count = " << leaf_count << endl;
565
566 assert(leaf_count == node_instance_count);
567 }
568
569 void dump_leaf_nodes() const
570 {
571 using ::std::cout;
572 using ::std::endl;
573
574 cout << "------------------------------------------" << endl;
575
576 node_ptr cur_node = m_left_leaf;
577 long node_id = 0;
578 while (cur_node)
579 {
580 cout << " node " << node_id++ << ": key = " << cur_node->key << "; value = " << cur_node->value_leaf.value
581 << endl;
582 cur_node = cur_node->next;
583 }
584 cout << endl << " node instance count = " << node::get_instance_count() << endl;
585 }
586
594 bool verify_keys(const ::std::vector<key_type>& key_values) const
595 {
596 {
597 // Start from the left-most node, and traverse right.
598 node* cur_node = m_left_leaf.get();
599 typename ::std::vector<key_type>::const_iterator itr = key_values.begin(), itr_end = key_values.end();
600 for (; itr != itr_end; ++itr)
601 {
602 if (!cur_node)
603 // Position past the right-mode node. Invalid.
604 return false;
605
606 if (cur_node->key != *itr)
607 // Key values differ.
608 return false;
609
610 cur_node = cur_node->next.get();
611 }
612
613 if (cur_node)
614 // At this point, we expect the current node to be at the position
615 // past the right-most node, which is nullptr.
616 return false;
617 }
618
619 {
620 // Start from the right-most node, and traverse left.
621 node* cur_node = m_right_leaf.get();
622 typename ::std::vector<key_type>::const_reverse_iterator itr = key_values.rbegin(),
623 itr_end = key_values.rend();
624 for (; itr != itr_end; ++itr)
625 {
626 if (!cur_node)
627 // Position past the left-mode node. Invalid.
628 return false;
629
630 if (cur_node->key != *itr)
631 // Key values differ.
632 return false;
633
634 cur_node = cur_node->prev.get();
635 }
636
637 if (cur_node)
638 // Likewise, we expect the current position to be past the
639 // left-most node, in which case the node value is nullptr.
640 return false;
641 }
642
643 return true;
644 }
645
653 bool verify_values(const ::std::vector<value_type>& values) const
654 {
655 node* cur_node = m_left_leaf.get();
656 node* end_node = m_right_leaf.get();
657 typename ::std::vector<value_type>::const_iterator itr = values.begin(), itr_end = values.end();
658 for (; itr != itr_end; ++itr)
659 {
660 if (cur_node == end_node || !cur_node)
661 return false;
662
663 if (cur_node->value_leaf.value != *itr)
664 // Key values differ.
665 return false;
666
667 cur_node = cur_node->next.get();
668 }
669
670 if (cur_node != end_node)
671 // At this point, we expect the current node to be at the end of
672 // range.
673 return false;
674
675 return true;
676 }
677#endif
678
679private:
680 const_iterator search_by_key_impl(const node* start_pos, key_type key) const;
681
682 const node* search_tree_for_leaf_node(key_type key) const;
683
684 void append_new_segment(key_type start_key)
685 {
686 if (m_right_leaf->prev->key == start_key)
687 {
688 m_right_leaf->prev->value_leaf.value = m_init_val;
689 return;
690 }
691
692#ifdef MDDS_UNIT_TEST
693 // The start position must come after the position of the last node
694 // before the right-most node.
695 assert(m_right_leaf->prev->key < start_key);
696#endif
697
698 if (m_right_leaf->prev->value_leaf.value == m_init_val)
699 // The existing segment has the same value. No need to insert a
700 // new segment.
701 return;
702
703 node_ptr new_node(new node);
704 new_node->key = start_key;
705 new_node->value_leaf.value = m_init_val;
706 new_node->prev = m_right_leaf->prev;
707 new_node->next = m_right_leaf;
708 m_right_leaf->prev->next = new_node;
709 m_right_leaf->prev = std::move(new_node);
710 m_valid_tree = false;
711 }
712
713 ::std::pair<const_iterator, bool> insert_segment_impl(
714 key_type start_key, key_type end_key, value_type val, bool forward);
715
716 ::std::pair<const_iterator, bool> insert_to_pos(
717 node_ptr start_pos, key_type start_key, key_type end_key, value_type val);
718
719 ::std::pair<const_iterator, bool> search_impl(
720 const node* pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const;
721
722 const node* get_insertion_pos_leaf_reverse(const key_type& key, const node* start_pos) const;
723
734 const node* get_insertion_pos_leaf(const key_type& key, const node* start_pos) const;
735
736 static void shift_leaf_key_left(node_ptr& begin_node, node_ptr& end_node, key_type shift_value)
737 {
738 node* cur_node_p = begin_node.get();
739 node* end_node_p = end_node.get();
740 while (cur_node_p != end_node_p)
741 {
742 cur_node_p->key -= shift_value;
743 cur_node_p = cur_node_p->next.get();
744 }
745 }
746
747 static void shift_leaf_key_right(node_ptr& cur_node, node_ptr& end_node, key_type shift_value)
748 {
749 key_type end_node_key = end_node->key;
750 while (cur_node.get() != end_node.get())
751 {
752 cur_node->key += shift_value;
753 if (cur_node->key < end_node_key)
754 {
755 // The node is still in-bound. Keep shifting.
756 cur_node = cur_node->next;
757 continue;
758 }
759
760 // This node has been pushed outside the end node position.
761 // Remove all nodes that follows, and connect the previous node
762 // with the end node.
763
764 node_ptr last_node = cur_node->prev;
765 while (cur_node.get() != end_node.get())
766 {
767 node_ptr next_node = cur_node->next;
768 disconnect_all_nodes(cur_node.get());
769 cur_node = std::move(next_node);
770 }
771 last_node->next = end_node;
772 end_node->prev = std::move(last_node);
773 return;
774 }
775 }
776
777 void destroy();
778
786 bool adjust_segment_range(key_type& start_key, key_type& end_key) const;
787
788private:
789 std::vector<nonleaf_node> m_nonleaf_node_pool;
790
791 const nonleaf_node* m_root_node;
792 node_ptr m_left_leaf;
793 node_ptr m_right_leaf;
794 value_type m_init_val;
795 bool m_valid_tree;
796};
797
798template<typename Key, typename Value>
799void swap(flat_segment_tree<Key, Value>& left, flat_segment_tree<Key, Value>& right) noexcept(
800 std::is_nothrow_swappable_v<flat_segment_tree<Key, Value>>)
801{
802 left.swap(right);
803}
804
805} // namespace mdds
806
807#include "flat_segment_tree_def.inl"
808
809/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition flat_segment_tree.hpp:87
const_segment_iterator to_segment() const
Definition flat_segment_tree.hpp:117
Definition flat_segment_tree.hpp:133
Definition flat_segment_tree.hpp:28
flat_segment_tree(flat_segment_tree &&other) noexcept(nothrow_move_constructible_v)
const_segment_range_type segment_range() const
flat_segment_tree< Key, Value > & operator=(const flat_segment_tree &other)
void shift_left(key_type start_key, key_type end_key)
flat_segment_tree(const flat_segment_tree &r)
void swap(flat_segment_tree &other) noexcept(nothrow_swappable_v)
void shift_right(key_type pos, key_type size, bool skip_start_node)
const_segment_iterator end_segment() const
const_iterator search(const_iterator pos, key_type key) const
const_reverse_iterator rbegin() const
Definition flat_segment_tree.hpp:177
std::pair< const_iterator, bool > insert_front(key_type start_key, key_type end_key, value_type val)
Definition flat_segment_tree.hpp:300
flat_segment_tree< Key, Value > & operator=(flat_segment_tree &&other) noexcept(nothrow_move_assignable_v)
const_iterator begin() const
Definition flat_segment_tree.hpp:151
std::pair< const_iterator, bool > search(key_type key, value_type &value, key_type *start_key=nullptr, key_type *end_key=nullptr) const
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:516
bool valid_tree() const noexcept
Definition flat_segment_tree.hpp:479
std::pair< const_iterator, bool > search_tree(key_type key, value_type &value, key_type *start_key=nullptr, key_type *end_key=nullptr) const
std::pair< const_iterator, bool > insert_back(key_type start_key, key_type end_key, value_type val)
Definition flat_segment_tree.hpp:320
const_segment_iterator begin_segment() const
const_iterator search(key_type key) const
bool operator==(const flat_segment_tree &other) const noexcept(nothrow_eq_comparable_v)
const_iterator end() const
Definition flat_segment_tree.hpp:164
flat_segment_tree(key_type min_val, key_type max_val, value_type init_val)
std::pair< const_iterator, bool > insert(const_iterator pos, key_type start_key, key_type end_key, value_type val)
const_iterator search_tree(key_type key) const
const_reverse_iterator rend() const
Definition flat_segment_tree.hpp:191
std::pair< const_iterator, bool > search(const_iterator pos, key_type key, value_type &value, key_type *start_key=nullptr, key_type *end_key=nullptr) const
Definition flat_segment_tree_itr.hpp:74
Definition flat_segment_tree_itr.hpp:171
Definition flat_segment_tree.hpp:35
Definition flat_segment_tree_itr.hpp:17
Definition flat_segment_tree_itr.hpp:47
Definition node.hpp:106
Definition node.hpp:40