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
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
691private:
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
800private:
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
810template<typename Key, typename Value>
811void 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: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)
bool is_tree_valid() const noexcept
Definition flat_segment_tree.hpp:491
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:528
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