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 *
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
46namespace mdds {
47
48template<typename Key, typename Value>
50{
51public:
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
82private:
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
86public:
88
90 flat_segment_tree, ::mdds::fst::detail::forward_itr_handler<flat_segment_tree>>
91 {
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 {
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
211
224
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
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
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
680private:
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
789private:
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
799template<typename Key, typename Value>
800void 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:91
const_segment_iterator to_segment() const
Definition flat_segment_tree.hpp:121
Definition flat_segment_tree.hpp:137
Definition flat_segment_tree.hpp:50
size_type leaf_size() const
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)
flat_segment_tree(flat_segment_tree &&other)
flat_segment_tree< Key, Value > & operator=(flat_segment_tree &&other)
void shift_right(key_type pos, key_type size, bool skip_start_node)
const_segment_iterator end_segment() const
bool operator==(const flat_segment_tree &other) const
const_reverse_iterator rbegin() const
Definition flat_segment_tree.hpp:181
const_iterator search(const const_iterator &pos, key_type key) const
std::pair< const_iterator, bool > insert_front(key_type start_key, key_type end_key, value_type val)
Definition flat_segment_tree.hpp:304
const_iterator begin() const
Definition flat_segment_tree.hpp:155
std::pair< const_iterator, bool > search(key_type key, value_type &value, key_type *start_key=nullptr, key_type *end_key=nullptr) const
bool valid_tree() const noexcept
Definition flat_segment_tree.hpp:484
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(const const_iterator &pos, key_type start_key, key_type end_key, value_type val)
std::pair< const_iterator, bool > search(const const_iterator &pos, 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:324
const_segment_iterator begin_segment() const
const_iterator search(key_type key) const
void swap(flat_segment_tree &other)
const_iterator end() const
Definition flat_segment_tree.hpp:168
flat_segment_tree(key_type min_val, key_type max_val, value_type init_val)
const_iterator search_tree(key_type key) const
const_reverse_iterator rend() const
Definition flat_segment_tree.hpp:195
Definition flat_segment_tree_itr.hpp:95
Definition flat_segment_tree_itr.hpp:199
Definition node.hpp:427
Definition flat_segment_tree.hpp:61
Definition flat_segment_tree.hpp:57
Definition flat_segment_tree_itr.hpp:38
Definition flat_segment_tree_itr.hpp:68
Definition node.hpp:123
Definition node.hpp:64