/src/mdds-3.1.0/include/mdds/flat_segment_tree_def.inl
Line | Count | Source |
1 | | /************************************************************************* |
2 | | * |
3 | | * Copyright (c) 2010-2023 Kohei Yoshida |
4 | | * |
5 | | * Permission is hereby granted, free of charge, to any person |
6 | | * obtaining a copy of this software and associated documentation |
7 | | * files (the "Software"), to deal in the Software without |
8 | | * restriction, including without limitation the rights to use, |
9 | | * copy, modify, merge, publish, distribute, sublicense, and/or sell |
10 | | * copies of the Software, and to permit persons to whom the |
11 | | * Software is furnished to do so, subject to the following |
12 | | * conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice shall be |
15 | | * included in all copies or substantial portions of the Software. |
16 | | * |
17 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
18 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
19 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
20 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
21 | | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
22 | | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
23 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
24 | | * OTHER DEALINGS IN THE SOFTWARE. |
25 | | * |
26 | | ************************************************************************/ |
27 | | |
28 | | namespace mdds { |
29 | | |
30 | | template<typename Key, typename Value> |
31 | | typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree< |
32 | | Key, Value>::const_iterator::to_segment() const |
33 | | { |
34 | | const node* pos = get_pos(); |
35 | | const auto* parent = get_parent(); |
36 | | if (!parent || is_end_pos() || !pos || !pos->next) |
37 | | return parent->end_segment(); |
38 | | |
39 | | return const_segment_iterator(pos, pos->next.get()); |
40 | | } |
41 | | |
42 | | template<typename Key, typename Value> |
43 | | flat_segment_tree<Key, Value>::const_segment_range_type::const_segment_range_type( |
44 | | node_ptr left_leaf, node_ptr right_leaf) |
45 | | : m_left_leaf(left_leaf), m_right_leaf(right_leaf) |
46 | | {} |
47 | | |
48 | | template<typename Key, typename Value> |
49 | | typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree< |
50 | | Key, Value>::const_segment_range_type::begin() const |
51 | | { |
52 | | return const_segment_iterator(m_left_leaf.get(), m_left_leaf->next.get()); |
53 | | } |
54 | | |
55 | | template<typename Key, typename Value> |
56 | | typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree< |
57 | | Key, Value>::const_segment_range_type::end() const |
58 | | { |
59 | | return const_segment_iterator(m_right_leaf.get(), nullptr); |
60 | | } |
61 | | |
62 | | template<typename Key, typename Value> |
63 | | typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree<Key, Value>::begin_segment() const |
64 | | { |
65 | | return const_segment_iterator(m_left_leaf.get(), m_left_leaf->next.get()); |
66 | | } |
67 | | |
68 | | template<typename Key, typename Value> |
69 | | typename flat_segment_tree<Key, Value>::const_segment_iterator flat_segment_tree<Key, Value>::end_segment() const |
70 | | { |
71 | | return const_segment_iterator(m_right_leaf.get(), nullptr); |
72 | | } |
73 | | |
74 | | template<typename Key, typename Value> |
75 | | typename flat_segment_tree<Key, Value>::const_segment_range_type flat_segment_tree<Key, Value>::segment_range() const |
76 | | { |
77 | | return const_segment_range_type(m_left_leaf, m_right_leaf); |
78 | | } |
79 | | |
80 | | template<typename Key, typename Value> |
81 | | flat_segment_tree<Key, Value>::flat_segment_tree(key_type min_val, key_type max_val, value_type init_val) |
82 | 561 | : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)), |
83 | 561 | m_valid_tree(false) |
84 | 561 | { |
85 | | // we need to create two end nodes during initialization. |
86 | 561 | m_left_leaf->key = std::move(min_val); |
87 | 561 | m_left_leaf->value_leaf.value = m_init_val; // copy |
88 | 561 | m_left_leaf->next = m_right_leaf; |
89 | | |
90 | 561 | m_right_leaf->key = std::move(max_val); |
91 | 561 | m_right_leaf->prev = m_left_leaf; |
92 | | |
93 | | // We don't ever use the value of the right leaf node, but we need the |
94 | | // value to be always the same, to make it easier to check for |
95 | | // equality. |
96 | 561 | m_right_leaf->value_leaf.value = value_type{}; |
97 | 561 | } mdds::flat_segment_tree<unsigned int, float>::flat_segment_tree(unsigned int, unsigned int, float) Line | Count | Source | 82 | 212 | : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)), | 83 | 212 | m_valid_tree(false) | 84 | 212 | { | 85 | | // we need to create two end nodes during initialization. | 86 | 212 | m_left_leaf->key = std::move(min_val); | 87 | 212 | m_left_leaf->value_leaf.value = m_init_val; // copy | 88 | 212 | m_left_leaf->next = m_right_leaf; | 89 | | | 90 | 212 | m_right_leaf->key = std::move(max_val); | 91 | 212 | m_right_leaf->prev = m_left_leaf; | 92 | | | 93 | | // We don't ever use the value of the right leaf node, but we need the | 94 | | // value to be always the same, to make it easier to check for | 95 | | // equality. | 96 | 212 | m_right_leaf->value_leaf.value = value_type{}; | 97 | 212 | } |
mdds::flat_segment_tree<unsigned int, bool>::flat_segment_tree(unsigned int, unsigned int, bool) Line | Count | Source | 82 | 212 | : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)), | 83 | 212 | m_valid_tree(false) | 84 | 212 | { | 85 | | // we need to create two end nodes during initialization. | 86 | 212 | m_left_leaf->key = std::move(min_val); | 87 | 212 | m_left_leaf->value_leaf.value = m_init_val; // copy | 88 | 212 | m_left_leaf->next = m_right_leaf; | 89 | | | 90 | 212 | m_right_leaf->key = std::move(max_val); | 91 | 212 | m_right_leaf->prev = m_left_leaf; | 92 | | | 93 | | // We don't ever use the value of the right leaf node, but we need the | 94 | | // value to be always the same, to make it easier to check for | 95 | | // equality. | 96 | 212 | m_right_leaf->value_leaf.value = value_type{}; | 97 | 212 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::flat_segment_tree(unsigned int, unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle>) Line | Count | Source | 82 | 137 | : m_root_node(nullptr), m_left_leaf(new node), m_right_leaf(new node), m_init_val(std::move(init_val)), | 83 | 137 | m_valid_tree(false) | 84 | 137 | { | 85 | | // we need to create two end nodes during initialization. | 86 | 137 | m_left_leaf->key = std::move(min_val); | 87 | 137 | m_left_leaf->value_leaf.value = m_init_val; // copy | 88 | 137 | m_left_leaf->next = m_right_leaf; | 89 | | | 90 | 137 | m_right_leaf->key = std::move(max_val); | 91 | 137 | m_right_leaf->prev = m_left_leaf; | 92 | | | 93 | | // We don't ever use the value of the right leaf node, but we need the | 94 | | // value to be always the same, to make it easier to check for | 95 | | // equality. | 96 | 137 | m_right_leaf->value_leaf.value = value_type{}; | 97 | 137 | } |
|
98 | | |
99 | | template<typename Key, typename Value> |
100 | | flat_segment_tree<Key, Value>::flat_segment_tree(const flat_segment_tree& r) |
101 | 136 | : m_root_node(nullptr), m_left_leaf(new node(*r.m_left_leaf)), m_right_leaf(), m_init_val(r.m_init_val), |
102 | 136 | m_valid_tree(false) // tree is invalid because we only copy the leaf nodes. |
103 | 136 | { |
104 | | // Copy all the leaf nodes from the original instance. |
105 | 136 | node* src_node = r.m_left_leaf.get(); |
106 | 136 | node_ptr dest_node = m_left_leaf; |
107 | 402 | while (true) |
108 | 402 | { |
109 | 402 | dest_node->next.reset(new node(*src_node->next)); |
110 | | |
111 | | // Move on to the next source node. |
112 | 402 | src_node = src_node->next.get(); |
113 | | |
114 | | // Move on to the next destination node, and have the next node point |
115 | | // back to the previous node. |
116 | 402 | node_ptr old_node = dest_node; |
117 | 402 | dest_node = dest_node->next; |
118 | 402 | dest_node->prev = std::move(old_node); |
119 | | |
120 | 402 | if (src_node == r.m_right_leaf.get()) |
121 | 136 | { |
122 | | // Reached the right most leaf node. We can stop here. |
123 | 136 | m_right_leaf = dest_node; |
124 | 136 | break; |
125 | 136 | } |
126 | 402 | } |
127 | 136 | } |
128 | | |
129 | | template<typename Key, typename Value> |
130 | | flat_segment_tree<Key, Value>::flat_segment_tree(flat_segment_tree&& other) |
131 | 274 | : m_nonleaf_node_pool(std::move(other.m_nonleaf_node_pool)), m_root_node(other.m_root_node), |
132 | 274 | m_left_leaf(other.m_left_leaf), m_right_leaf(other.m_right_leaf), m_init_val(other.m_init_val), |
133 | 274 | m_valid_tree(other.m_valid_tree) |
134 | 274 | { |
135 | | // NB: boost::intrusive_ptr doesn't have move constructor |
136 | 274 | other.m_left_leaf.reset(); |
137 | 274 | other.m_right_leaf.reset(); |
138 | 274 | other.m_root_node = nullptr; |
139 | 274 | other.m_valid_tree = false; |
140 | 274 | } |
141 | | |
142 | | template<typename Key, typename Value> |
143 | | flat_segment_tree<Key, Value>::~flat_segment_tree() |
144 | 971 | { |
145 | 971 | destroy(); |
146 | 971 | } mdds::flat_segment_tree<unsigned int, bool>::~flat_segment_tree() Line | Count | Source | 144 | 212 | { | 145 | 212 | destroy(); | 146 | 212 | } |
mdds::flat_segment_tree<unsigned int, float>::~flat_segment_tree() Line | Count | Source | 144 | 212 | { | 145 | 212 | destroy(); | 146 | 212 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::~flat_segment_tree() Line | Count | Source | 144 | 547 | { | 145 | 547 | destroy(); | 146 | 547 | } |
|
147 | | |
148 | | template<typename Key, typename Value> |
149 | | flat_segment_tree<Key, Value>& flat_segment_tree<Key, Value>::operator=(const flat_segment_tree& other) |
150 | 0 | { |
151 | 0 | flat_segment_tree copy(other); |
152 | 0 | swap(copy); |
153 | 0 | return *this; |
154 | 0 | } |
155 | | |
156 | | template<typename Key, typename Value> |
157 | | flat_segment_tree<Key, Value>& flat_segment_tree<Key, Value>::operator=(flat_segment_tree&& other) |
158 | | { |
159 | | flat_segment_tree moved(std::move(other)); |
160 | | swap(moved); |
161 | | return *this; |
162 | | } |
163 | | |
164 | | template<typename Key, typename Value> |
165 | | void flat_segment_tree<Key, Value>::swap(flat_segment_tree& other) |
166 | 0 | { |
167 | 0 | m_nonleaf_node_pool.swap(other.m_nonleaf_node_pool); |
168 | 0 | std::swap(m_root_node, other.m_root_node); |
169 | 0 | std::swap(m_left_leaf, other.m_left_leaf); |
170 | 0 | std::swap(m_right_leaf, other.m_right_leaf); |
171 | 0 | std::swap(m_init_val, other.m_init_val); |
172 | 0 | std::swap(m_valid_tree, other.m_valid_tree); |
173 | 0 | } |
174 | | |
175 | | template<typename Key, typename Value> |
176 | | void flat_segment_tree<Key, Value>::clear() |
177 | | { |
178 | | // the border nodes should not be destroyed--add a ref to keep them alive |
179 | | node_ptr left(m_left_leaf); |
180 | | node_ptr right(m_right_leaf); |
181 | | |
182 | | // destroy the tree |
183 | | destroy(); |
184 | | |
185 | | // and construct the default tree |
186 | | st::detail::link_nodes<node_ptr>(m_left_leaf, m_right_leaf); |
187 | | m_left_leaf->value_leaf.value = m_init_val; |
188 | | m_valid_tree = false; |
189 | | } |
190 | | |
191 | | template<typename Key, typename Value> |
192 | | ::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree< |
193 | | Key, Value>::insert_segment_impl(key_type start_key, key_type end_key, value_type val, bool forward) |
194 | 1.44k | { |
195 | 1.44k | typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type; |
196 | | |
197 | 1.44k | if (!adjust_segment_range(start_key, end_key)) |
198 | 0 | return ret_type(const_iterator(this, true), false); |
199 | | |
200 | | // Find the node with value that either equals or is greater than the |
201 | | // start value. |
202 | | |
203 | 1.44k | node_ptr start_pos; |
204 | 1.44k | if (forward) |
205 | 0 | { |
206 | 0 | const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get()); |
207 | 0 | start_pos.reset(const_cast<node*>(p)); |
208 | 0 | } |
209 | 1.44k | else |
210 | 1.44k | { |
211 | 1.44k | const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get()); |
212 | 1.44k | if (p) |
213 | 1.11k | start_pos = p->next; |
214 | 326 | else |
215 | 326 | start_pos = m_left_leaf; |
216 | 1.44k | } |
217 | 1.44k | if (!start_pos) |
218 | 0 | { |
219 | | // Insertion position not found. Bail out. |
220 | 0 | assert(!"Insertion position not found. Bail out"); |
221 | 0 | return ret_type(const_iterator(this, true), false); |
222 | 0 | } |
223 | | |
224 | 1.44k | return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val)); |
225 | 1.44k | } mdds::flat_segment_tree<unsigned int, float>::insert_segment_impl(unsigned int, unsigned int, float, bool) Line | Count | Source | 194 | 656 | { | 195 | 656 | typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type; | 196 | | | 197 | 656 | if (!adjust_segment_range(start_key, end_key)) | 198 | 0 | return ret_type(const_iterator(this, true), false); | 199 | | | 200 | | // Find the node with value that either equals or is greater than the | 201 | | // start value. | 202 | | | 203 | 656 | node_ptr start_pos; | 204 | 656 | if (forward) | 205 | 0 | { | 206 | 0 | const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get()); | 207 | 0 | start_pos.reset(const_cast<node*>(p)); | 208 | 0 | } | 209 | 656 | else | 210 | 656 | { | 211 | 656 | const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get()); | 212 | 656 | if (p) | 213 | 492 | start_pos = p->next; | 214 | 164 | else | 215 | 164 | start_pos = m_left_leaf; | 216 | 656 | } | 217 | 656 | if (!start_pos) | 218 | 0 | { | 219 | | // Insertion position not found. Bail out. | 220 | 0 | assert(!"Insertion position not found. Bail out"); | 221 | 0 | return ret_type(const_iterator(this, true), false); | 222 | 0 | } | 223 | | | 224 | 656 | return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val)); | 225 | 656 | } |
mdds::flat_segment_tree<unsigned int, bool>::insert_segment_impl(unsigned int, unsigned int, bool, bool) Line | Count | Source | 194 | 651 | { | 195 | 651 | typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type; | 196 | | | 197 | 651 | if (!adjust_segment_range(start_key, end_key)) | 198 | 0 | return ret_type(const_iterator(this, true), false); | 199 | | | 200 | | // Find the node with value that either equals or is greater than the | 201 | | // start value. | 202 | | | 203 | 651 | node_ptr start_pos; | 204 | 651 | if (forward) | 205 | 0 | { | 206 | 0 | const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get()); | 207 | 0 | start_pos.reset(const_cast<node*>(p)); | 208 | 0 | } | 209 | 651 | else | 210 | 651 | { | 211 | 651 | const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get()); | 212 | 651 | if (p) | 213 | 489 | start_pos = p->next; | 214 | 162 | else | 215 | 162 | start_pos = m_left_leaf; | 216 | 651 | } | 217 | 651 | if (!start_pos) | 218 | 0 | { | 219 | | // Insertion position not found. Bail out. | 220 | 0 | assert(!"Insertion position not found. Bail out"); | 221 | 0 | return ret_type(const_iterator(this, true), false); | 222 | 0 | } | 223 | | | 224 | 651 | return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val)); | 225 | 651 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::insert_segment_impl(unsigned int, unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle>, bool) Line | Count | Source | 194 | 133 | { | 195 | 133 | typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type; | 196 | | | 197 | 133 | if (!adjust_segment_range(start_key, end_key)) | 198 | 0 | return ret_type(const_iterator(this, true), false); | 199 | | | 200 | | // Find the node with value that either equals or is greater than the | 201 | | // start value. | 202 | | | 203 | 133 | node_ptr start_pos; | 204 | 133 | if (forward) | 205 | 0 | { | 206 | 0 | const node* p = get_insertion_pos_leaf(start_key, m_left_leaf.get()); | 207 | 0 | start_pos.reset(const_cast<node*>(p)); | 208 | 0 | } | 209 | 133 | else | 210 | 133 | { | 211 | 133 | const node* p = get_insertion_pos_leaf_reverse(start_key, m_right_leaf.get()); | 212 | 133 | if (p) | 213 | 133 | start_pos = p->next; | 214 | 0 | else | 215 | 0 | start_pos = m_left_leaf; | 216 | 133 | } | 217 | 133 | if (!start_pos) | 218 | 0 | { | 219 | | // Insertion position not found. Bail out. | 220 | 0 | assert(!"Insertion position not found. Bail out"); | 221 | 0 | return ret_type(const_iterator(this, true), false); | 222 | 0 | } | 223 | | | 224 | 133 | return insert_to_pos(std::move(start_pos), std::move(start_key), std::move(end_key), std::move(val)); | 225 | 133 | } |
|
226 | | |
227 | | template<typename Key, typename Value> |
228 | | ::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::insert_to_pos( |
229 | | node_ptr start_pos, key_type start_key, key_type end_key, value_type val) |
230 | 1.44k | { |
231 | 1.44k | node_ptr end_pos; |
232 | 1.44k | { |
233 | 1.44k | const node* p = get_insertion_pos_leaf(end_key, start_pos.get()); |
234 | 1.44k | end_pos.reset(const_cast<node*>(p)); |
235 | 1.44k | } |
236 | 1.44k | if (!end_pos) |
237 | 0 | end_pos = m_right_leaf; |
238 | | |
239 | 1.44k | node_ptr new_start_node; |
240 | 1.44k | value_type old_value; |
241 | | |
242 | | // Set the start node. |
243 | | |
244 | 1.44k | bool changed = false; |
245 | | |
246 | 1.44k | if (start_pos->key == start_key) |
247 | 817 | { |
248 | | // Re-use the existing node, but save the old value for later. |
249 | | |
250 | 817 | if (start_pos->prev && start_pos->prev->value_leaf.value == val) |
251 | 490 | { |
252 | | // Extend the existing segment. |
253 | 490 | old_value = start_pos->value_leaf.value; |
254 | 490 | new_start_node = start_pos->prev; |
255 | 490 | } |
256 | 327 | else |
257 | 327 | { |
258 | | // Update the value of the existing node. |
259 | 327 | old_value = start_pos->value_leaf.value; |
260 | 327 | start_pos->value_leaf.value = val; |
261 | 327 | new_start_node = std::move(start_pos); |
262 | | |
263 | 327 | changed = (old_value != val); |
264 | 327 | } |
265 | 817 | } |
266 | 623 | else if (start_pos->prev->value_leaf.value == val) |
267 | 489 | { |
268 | | // Extend the existing segment. |
269 | 489 | old_value = start_pos->prev->value_leaf.value; |
270 | 489 | new_start_node = start_pos->prev; |
271 | 489 | } |
272 | 134 | else |
273 | 134 | { |
274 | | // Insert a new node before the insertion position node. |
275 | 134 | node_ptr new_node(new node); |
276 | 134 | new_node->key = std::move(start_key); |
277 | 134 | new_node->value_leaf.value = val; |
278 | 134 | new_start_node = new_node; |
279 | | |
280 | 134 | node_ptr left_node = start_pos->prev; |
281 | 134 | old_value = left_node->value_leaf.value; |
282 | | |
283 | | // Link to the left node. |
284 | 134 | st::detail::link_nodes<node_ptr>(left_node, new_node); |
285 | | |
286 | | // Link to the right node. |
287 | 134 | st::detail::link_nodes<node_ptr>(new_node, start_pos); |
288 | 134 | changed = true; |
289 | 134 | } |
290 | | |
291 | 1.44k | node_ptr cur_node = new_start_node->next; |
292 | 1.93k | while (cur_node != end_pos) |
293 | 490 | { |
294 | | // Disconnect the link between the current node and the previous node. |
295 | 490 | cur_node->prev->next.reset(); |
296 | 490 | cur_node->prev.reset(); |
297 | 490 | old_value = cur_node->value_leaf.value; |
298 | | |
299 | 490 | cur_node = cur_node->next; |
300 | 490 | changed = true; |
301 | 490 | } |
302 | | |
303 | | // Set the end node. |
304 | | |
305 | 1.44k | if (end_pos->key == end_key) |
306 | 184 | { |
307 | | // The new segment ends exactly at the end node position. |
308 | | |
309 | 184 | if (end_pos->next && end_pos->value_leaf.value == val) |
310 | 0 | { |
311 | | // Remove this node, and connect the new start node with the |
312 | | // node that comes after this node. |
313 | 0 | new_start_node->next = end_pos->next; |
314 | 0 | if (end_pos->next) |
315 | 0 | end_pos->next->prev = new_start_node; |
316 | 0 | disconnect_all_nodes(end_pos.get()); |
317 | 0 | changed = true; |
318 | 0 | } |
319 | 184 | else if (new_start_node->next != end_pos) |
320 | 90 | { |
321 | | // Just link the new segment to this node. |
322 | 90 | new_start_node->next = end_pos; |
323 | 90 | end_pos->prev = new_start_node; |
324 | 90 | changed = true; |
325 | 90 | } |
326 | 184 | } |
327 | 1.25k | else if (old_value == val) |
328 | 560 | { |
329 | 560 | if (new_start_node->next != end_pos) |
330 | 0 | { |
331 | 0 | st::detail::link_nodes<node_ptr>(new_start_node, end_pos); |
332 | 0 | changed = true; |
333 | 0 | } |
334 | 560 | } |
335 | 696 | else |
336 | 696 | { |
337 | | // Insert a new node before the insertion position node. |
338 | 696 | node_ptr new_node(new node); |
339 | 696 | new_node->key = std::move(end_key); |
340 | 696 | new_node->value_leaf.value = std::move(old_value); |
341 | | |
342 | | // Link to the left node. |
343 | 696 | st::detail::link_nodes<node_ptr>(new_start_node, new_node); |
344 | | |
345 | | // Link to the right node. |
346 | 696 | st::detail::link_nodes<node_ptr>(new_node, end_pos); |
347 | 696 | changed = true; |
348 | 696 | } |
349 | | |
350 | 1.44k | if (changed) |
351 | 788 | m_valid_tree = false; |
352 | | |
353 | 1.44k | return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed); |
354 | 1.44k | } mdds::flat_segment_tree<unsigned int, float>::insert_to_pos(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> >, unsigned int, unsigned int, float) Line | Count | Source | 230 | 656 | { | 231 | 656 | node_ptr end_pos; | 232 | 656 | { | 233 | 656 | const node* p = get_insertion_pos_leaf(end_key, start_pos.get()); | 234 | 656 | end_pos.reset(const_cast<node*>(p)); | 235 | 656 | } | 236 | 656 | if (!end_pos) | 237 | 0 | end_pos = m_right_leaf; | 238 | | | 239 | 656 | node_ptr new_start_node; | 240 | 656 | value_type old_value; | 241 | | | 242 | | // Set the start node. | 243 | | | 244 | 656 | bool changed = false; | 245 | | | 246 | 656 | if (start_pos->key == start_key) | 247 | 655 | { | 248 | | // Re-use the existing node, but save the old value for later. | 249 | | | 250 | 655 | if (start_pos->prev && start_pos->prev->value_leaf.value == val) | 251 | 490 | { | 252 | | // Extend the existing segment. | 253 | 490 | old_value = start_pos->value_leaf.value; | 254 | 490 | new_start_node = start_pos->prev; | 255 | 490 | } | 256 | 165 | else | 257 | 165 | { | 258 | | // Update the value of the existing node. | 259 | 165 | old_value = start_pos->value_leaf.value; | 260 | 165 | start_pos->value_leaf.value = val; | 261 | 165 | new_start_node = std::move(start_pos); | 262 | | | 263 | 165 | changed = (old_value != val); | 264 | 165 | } | 265 | 655 | } | 266 | 1 | else if (start_pos->prev->value_leaf.value == val) | 267 | 0 | { | 268 | | // Extend the existing segment. | 269 | 0 | old_value = start_pos->prev->value_leaf.value; | 270 | 0 | new_start_node = start_pos->prev; | 271 | 0 | } | 272 | 1 | else | 273 | 1 | { | 274 | | // Insert a new node before the insertion position node. | 275 | 1 | node_ptr new_node(new node); | 276 | 1 | new_node->key = std::move(start_key); | 277 | 1 | new_node->value_leaf.value = val; | 278 | 1 | new_start_node = new_node; | 279 | | | 280 | 1 | node_ptr left_node = start_pos->prev; | 281 | 1 | old_value = left_node->value_leaf.value; | 282 | | | 283 | | // Link to the left node. | 284 | 1 | st::detail::link_nodes<node_ptr>(left_node, new_node); | 285 | | | 286 | | // Link to the right node. | 287 | 1 | st::detail::link_nodes<node_ptr>(new_node, start_pos); | 288 | 1 | changed = true; | 289 | 1 | } | 290 | | | 291 | 656 | node_ptr cur_node = new_start_node->next; | 292 | 1.14k | while (cur_node != end_pos) | 293 | 490 | { | 294 | | // Disconnect the link between the current node and the previous node. | 295 | 490 | cur_node->prev->next.reset(); | 296 | 490 | cur_node->prev.reset(); | 297 | 490 | old_value = cur_node->value_leaf.value; | 298 | | | 299 | 490 | cur_node = cur_node->next; | 300 | 490 | changed = true; | 301 | 490 | } | 302 | | | 303 | | // Set the end node. | 304 | | | 305 | 656 | if (end_pos->key == end_key) | 306 | 92 | { | 307 | | // The new segment ends exactly at the end node position. | 308 | | | 309 | 92 | if (end_pos->next && end_pos->value_leaf.value == val) | 310 | 0 | { | 311 | | // Remove this node, and connect the new start node with the | 312 | | // node that comes after this node. | 313 | 0 | new_start_node->next = end_pos->next; | 314 | 0 | if (end_pos->next) | 315 | 0 | end_pos->next->prev = new_start_node; | 316 | 0 | disconnect_all_nodes(end_pos.get()); | 317 | 0 | changed = true; | 318 | 0 | } | 319 | 92 | else if (new_start_node->next != end_pos) | 320 | 90 | { | 321 | | // Just link the new segment to this node. | 322 | 90 | new_start_node->next = end_pos; | 323 | 90 | end_pos->prev = new_start_node; | 324 | 90 | changed = true; | 325 | 90 | } | 326 | 92 | } | 327 | 564 | else if (old_value == val) | 328 | 1 | { | 329 | 1 | if (new_start_node->next != end_pos) | 330 | 0 | { | 331 | 0 | st::detail::link_nodes<node_ptr>(new_start_node, end_pos); | 332 | 0 | changed = true; | 333 | 0 | } | 334 | 1 | } | 335 | 563 | else | 336 | 563 | { | 337 | | // Insert a new node before the insertion position node. | 338 | 563 | node_ptr new_node(new node); | 339 | 563 | new_node->key = std::move(end_key); | 340 | 563 | new_node->value_leaf.value = std::move(old_value); | 341 | | | 342 | | // Link to the left node. | 343 | 563 | st::detail::link_nodes<node_ptr>(new_start_node, new_node); | 344 | | | 345 | | // Link to the right node. | 346 | 563 | st::detail::link_nodes<node_ptr>(new_node, end_pos); | 347 | 563 | changed = true; | 348 | 563 | } | 349 | | | 350 | 656 | if (changed) | 351 | 655 | m_valid_tree = false; | 352 | | | 353 | 656 | return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed); | 354 | 656 | } |
mdds::flat_segment_tree<unsigned int, bool>::insert_to_pos(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> >, unsigned int, unsigned int, bool) Line | Count | Source | 230 | 651 | { | 231 | 651 | node_ptr end_pos; | 232 | 651 | { | 233 | 651 | const node* p = get_insertion_pos_leaf(end_key, start_pos.get()); | 234 | 651 | end_pos.reset(const_cast<node*>(p)); | 235 | 651 | } | 236 | 651 | if (!end_pos) | 237 | 0 | end_pos = m_right_leaf; | 238 | | | 239 | 651 | node_ptr new_start_node; | 240 | 651 | value_type old_value; | 241 | | | 242 | | // Set the start node. | 243 | | | 244 | 651 | bool changed = false; | 245 | | | 246 | 651 | if (start_pos->key == start_key) | 247 | 162 | { | 248 | | // Re-use the existing node, but save the old value for later. | 249 | | | 250 | 162 | if (start_pos->prev && start_pos->prev->value_leaf.value == val) | 251 | 0 | { | 252 | | // Extend the existing segment. | 253 | 0 | old_value = start_pos->value_leaf.value; | 254 | 0 | new_start_node = start_pos->prev; | 255 | 0 | } | 256 | 162 | else | 257 | 162 | { | 258 | | // Update the value of the existing node. | 259 | 162 | old_value = start_pos->value_leaf.value; | 260 | 162 | start_pos->value_leaf.value = val; | 261 | 162 | new_start_node = std::move(start_pos); | 262 | | | 263 | 162 | changed = (old_value != val); | 264 | 162 | } | 265 | 162 | } | 266 | 489 | else if (start_pos->prev->value_leaf.value == val) | 267 | 489 | { | 268 | | // Extend the existing segment. | 269 | 489 | old_value = start_pos->prev->value_leaf.value; | 270 | 489 | new_start_node = start_pos->prev; | 271 | 489 | } | 272 | 0 | else | 273 | 0 | { | 274 | | // Insert a new node before the insertion position node. | 275 | 0 | node_ptr new_node(new node); | 276 | 0 | new_node->key = std::move(start_key); | 277 | 0 | new_node->value_leaf.value = val; | 278 | 0 | new_start_node = new_node; | 279 | |
| 280 | 0 | node_ptr left_node = start_pos->prev; | 281 | 0 | old_value = left_node->value_leaf.value; | 282 | | | 283 | | // Link to the left node. | 284 | 0 | st::detail::link_nodes<node_ptr>(left_node, new_node); | 285 | | | 286 | | // Link to the right node. | 287 | 0 | st::detail::link_nodes<node_ptr>(new_node, start_pos); | 288 | 0 | changed = true; | 289 | 0 | } | 290 | | | 291 | 651 | node_ptr cur_node = new_start_node->next; | 292 | 651 | while (cur_node != end_pos) | 293 | 0 | { | 294 | | // Disconnect the link between the current node and the previous node. | 295 | 0 | cur_node->prev->next.reset(); | 296 | 0 | cur_node->prev.reset(); | 297 | 0 | old_value = cur_node->value_leaf.value; | 298 | |
| 299 | 0 | cur_node = cur_node->next; | 300 | 0 | changed = true; | 301 | 0 | } | 302 | | | 303 | | // Set the end node. | 304 | | | 305 | 651 | if (end_pos->key == end_key) | 306 | 92 | { | 307 | | // The new segment ends exactly at the end node position. | 308 | | | 309 | 92 | if (end_pos->next && end_pos->value_leaf.value == val) | 310 | 0 | { | 311 | | // Remove this node, and connect the new start node with the | 312 | | // node that comes after this node. | 313 | 0 | new_start_node->next = end_pos->next; | 314 | 0 | if (end_pos->next) | 315 | 0 | end_pos->next->prev = new_start_node; | 316 | 0 | disconnect_all_nodes(end_pos.get()); | 317 | 0 | changed = true; | 318 | 0 | } | 319 | 92 | else if (new_start_node->next != end_pos) | 320 | 0 | { | 321 | | // Just link the new segment to this node. | 322 | 0 | new_start_node->next = end_pos; | 323 | 0 | end_pos->prev = new_start_node; | 324 | 0 | changed = true; | 325 | 0 | } | 326 | 92 | } | 327 | 559 | else if (old_value == val) | 328 | 559 | { | 329 | 559 | if (new_start_node->next != end_pos) | 330 | 0 | { | 331 | 0 | st::detail::link_nodes<node_ptr>(new_start_node, end_pos); | 332 | 0 | changed = true; | 333 | 0 | } | 334 | 559 | } | 335 | 0 | else | 336 | 0 | { | 337 | | // Insert a new node before the insertion position node. | 338 | 0 | node_ptr new_node(new node); | 339 | 0 | new_node->key = std::move(end_key); | 340 | 0 | new_node->value_leaf.value = std::move(old_value); | 341 | | | 342 | | // Link to the left node. | 343 | 0 | st::detail::link_nodes<node_ptr>(new_start_node, new_node); | 344 | | | 345 | | // Link to the right node. | 346 | 0 | st::detail::link_nodes<node_ptr>(new_node, end_pos); | 347 | 0 | changed = true; | 348 | 0 | } | 349 | | | 350 | 651 | if (changed) | 351 | 0 | m_valid_tree = false; | 352 | | | 353 | 651 | return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed); | 354 | 651 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::insert_to_pos(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> >, unsigned int, unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle>) Line | Count | Source | 230 | 133 | { | 231 | 133 | node_ptr end_pos; | 232 | 133 | { | 233 | 133 | const node* p = get_insertion_pos_leaf(end_key, start_pos.get()); | 234 | 133 | end_pos.reset(const_cast<node*>(p)); | 235 | 133 | } | 236 | 133 | if (!end_pos) | 237 | 0 | end_pos = m_right_leaf; | 238 | | | 239 | 133 | node_ptr new_start_node; | 240 | 133 | value_type old_value; | 241 | | | 242 | | // Set the start node. | 243 | | | 244 | 133 | bool changed = false; | 245 | | | 246 | 133 | if (start_pos->key == start_key) | 247 | 0 | { | 248 | | // Re-use the existing node, but save the old value for later. | 249 | |
| 250 | 0 | if (start_pos->prev && start_pos->prev->value_leaf.value == val) | 251 | 0 | { | 252 | | // Extend the existing segment. | 253 | 0 | old_value = start_pos->value_leaf.value; | 254 | 0 | new_start_node = start_pos->prev; | 255 | 0 | } | 256 | 0 | else | 257 | 0 | { | 258 | | // Update the value of the existing node. | 259 | 0 | old_value = start_pos->value_leaf.value; | 260 | 0 | start_pos->value_leaf.value = val; | 261 | 0 | new_start_node = std::move(start_pos); | 262 | |
| 263 | 0 | changed = (old_value != val); | 264 | 0 | } | 265 | 0 | } | 266 | 133 | else if (start_pos->prev->value_leaf.value == val) | 267 | 0 | { | 268 | | // Extend the existing segment. | 269 | 0 | old_value = start_pos->prev->value_leaf.value; | 270 | 0 | new_start_node = start_pos->prev; | 271 | 0 | } | 272 | 133 | else | 273 | 133 | { | 274 | | // Insert a new node before the insertion position node. | 275 | 133 | node_ptr new_node(new node); | 276 | 133 | new_node->key = std::move(start_key); | 277 | 133 | new_node->value_leaf.value = val; | 278 | 133 | new_start_node = new_node; | 279 | | | 280 | 133 | node_ptr left_node = start_pos->prev; | 281 | 133 | old_value = left_node->value_leaf.value; | 282 | | | 283 | | // Link to the left node. | 284 | 133 | st::detail::link_nodes<node_ptr>(left_node, new_node); | 285 | | | 286 | | // Link to the right node. | 287 | 133 | st::detail::link_nodes<node_ptr>(new_node, start_pos); | 288 | 133 | changed = true; | 289 | 133 | } | 290 | | | 291 | 133 | node_ptr cur_node = new_start_node->next; | 292 | 133 | while (cur_node != end_pos) | 293 | 0 | { | 294 | | // Disconnect the link between the current node and the previous node. | 295 | 0 | cur_node->prev->next.reset(); | 296 | 0 | cur_node->prev.reset(); | 297 | 0 | old_value = cur_node->value_leaf.value; | 298 | |
| 299 | 0 | cur_node = cur_node->next; | 300 | 0 | changed = true; | 301 | 0 | } | 302 | | | 303 | | // Set the end node. | 304 | | | 305 | 133 | if (end_pos->key == end_key) | 306 | 0 | { | 307 | | // The new segment ends exactly at the end node position. | 308 | |
| 309 | 0 | if (end_pos->next && end_pos->value_leaf.value == val) | 310 | 0 | { | 311 | | // Remove this node, and connect the new start node with the | 312 | | // node that comes after this node. | 313 | 0 | new_start_node->next = end_pos->next; | 314 | 0 | if (end_pos->next) | 315 | 0 | end_pos->next->prev = new_start_node; | 316 | 0 | disconnect_all_nodes(end_pos.get()); | 317 | 0 | changed = true; | 318 | 0 | } | 319 | 0 | else if (new_start_node->next != end_pos) | 320 | 0 | { | 321 | | // Just link the new segment to this node. | 322 | 0 | new_start_node->next = end_pos; | 323 | 0 | end_pos->prev = new_start_node; | 324 | 0 | changed = true; | 325 | 0 | } | 326 | 0 | } | 327 | 133 | else if (old_value == val) | 328 | 0 | { | 329 | 0 | if (new_start_node->next != end_pos) | 330 | 0 | { | 331 | 0 | st::detail::link_nodes<node_ptr>(new_start_node, end_pos); | 332 | 0 | changed = true; | 333 | 0 | } | 334 | 0 | } | 335 | 133 | else | 336 | 133 | { | 337 | | // Insert a new node before the insertion position node. | 338 | 133 | node_ptr new_node(new node); | 339 | 133 | new_node->key = std::move(end_key); | 340 | 133 | new_node->value_leaf.value = std::move(old_value); | 341 | | | 342 | | // Link to the left node. | 343 | 133 | st::detail::link_nodes<node_ptr>(new_start_node, new_node); | 344 | | | 345 | | // Link to the right node. | 346 | 133 | st::detail::link_nodes<node_ptr>(new_node, end_pos); | 347 | 133 | changed = true; | 348 | 133 | } | 349 | | | 350 | 133 | if (changed) | 351 | 133 | m_valid_tree = false; | 352 | | | 353 | 133 | return ::std::pair<const_iterator, bool>(const_iterator(this, new_start_node.get()), changed); | 354 | 133 | } |
|
355 | | |
356 | | template<typename Key, typename Value> |
357 | | ::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::insert( |
358 | | const_iterator pos, key_type start_key, key_type end_key, value_type val) |
359 | | { |
360 | | const node* p = pos.get_pos(); |
361 | | if (!p || this != pos.get_parent()) |
362 | | { |
363 | | // Switch to normal insert. |
364 | | return insert_front(start_key, end_key, val); |
365 | | } |
366 | | |
367 | | assert(p->is_leaf); |
368 | | |
369 | | if (start_key < p->key) |
370 | | { |
371 | | // Specified position is already past the start key position. Not good. |
372 | | return insert_front(start_key, end_key, val); |
373 | | } |
374 | | |
375 | | if (!adjust_segment_range(start_key, end_key)) |
376 | | { |
377 | | typedef std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> ret_type; |
378 | | return ret_type(const_iterator(this, true), false); |
379 | | } |
380 | | |
381 | | p = get_insertion_pos_leaf(start_key, p); |
382 | | node_ptr start_pos(const_cast<node*>(p)); |
383 | | return insert_to_pos(std::move(start_pos), start_key, end_key, std::move(val)); |
384 | | } |
385 | | |
386 | | template<typename Key, typename Value> |
387 | | void flat_segment_tree<Key, Value>::shift_left(key_type start_key, key_type end_key) |
388 | | { |
389 | | if (start_key >= end_key) |
390 | | return; |
391 | | |
392 | | key_type left_leaf_key = m_left_leaf->key; |
393 | | key_type right_leaf_key = m_right_leaf->key; |
394 | | if (start_key < left_leaf_key || end_key < left_leaf_key) |
395 | | // invalid key value |
396 | | return; |
397 | | |
398 | | if (start_key > right_leaf_key || end_key > right_leaf_key) |
399 | | // invalid key value. |
400 | | return; |
401 | | |
402 | | node_ptr node_pos; |
403 | | if (left_leaf_key == start_key) |
404 | | node_pos = m_left_leaf; |
405 | | else |
406 | | { |
407 | | // Get the first node with a key value equal to or greater than the |
408 | | // start key value. But we want to skip the leftmost node. |
409 | | const node* p = get_insertion_pos_leaf(start_key, m_left_leaf->next.get()); |
410 | | node_pos.reset(const_cast<node*>(p)); |
411 | | } |
412 | | |
413 | | if (!node_pos) |
414 | | return; |
415 | | |
416 | | key_type segment_size = end_key - start_key; |
417 | | |
418 | | if (node_pos == m_right_leaf) |
419 | | { |
420 | | // The segment being removed begins after the last node before the |
421 | | // right-most node. |
422 | | |
423 | | if (right_leaf_key <= end_key) |
424 | | { |
425 | | // The end position equals or is past the right-most node. |
426 | | append_new_segment(start_key); |
427 | | } |
428 | | else |
429 | | { |
430 | | // The end position stops before the right-most node. Simply |
431 | | // append the blank segment to the end. |
432 | | append_new_segment(right_leaf_key - segment_size); |
433 | | } |
434 | | return; |
435 | | } |
436 | | |
437 | | if (end_key < node_pos->key) |
438 | | { |
439 | | // The removed segment does not overlap with any nodes. Simply |
440 | | // shift the key values of those nodes that come after the removed |
441 | | // segment. |
442 | | shift_leaf_key_left(node_pos, m_right_leaf, segment_size); |
443 | | append_new_segment(right_leaf_key - segment_size); |
444 | | m_valid_tree = false; |
445 | | return; |
446 | | } |
447 | | |
448 | | // Move the first node to the starting position, and from there search |
449 | | // for the first node whose key value is greater than the end value. |
450 | | node_pos->key = start_key; |
451 | | node_ptr start_pos = node_pos; |
452 | | node_pos = node_pos->next; |
453 | | value_type last_seg_value = start_pos->value_leaf.value; |
454 | | while (node_pos.get() != m_right_leaf.get() && node_pos->key <= end_key) |
455 | | { |
456 | | last_seg_value = node_pos->value_leaf.value; |
457 | | node_ptr next = node_pos->next; |
458 | | disconnect_all_nodes(node_pos.get()); |
459 | | node_pos = std::move(next); |
460 | | } |
461 | | |
462 | | start_pos->value_leaf.value = last_seg_value; |
463 | | start_pos->next = node_pos; |
464 | | node_pos->prev = start_pos; |
465 | | if (start_pos->prev && start_pos->prev->value_leaf.value == start_pos->value_leaf.value) |
466 | | { |
467 | | // Removing a segment resulted in two consecutive segments with |
468 | | // identical value. Combine them by removing the 2nd redundant |
469 | | // node. |
470 | | start_pos->prev->next = start_pos->next; |
471 | | start_pos->next->prev = start_pos->prev; |
472 | | disconnect_all_nodes(start_pos.get()); |
473 | | } |
474 | | |
475 | | shift_leaf_key_left(node_pos, m_right_leaf, segment_size); |
476 | | m_valid_tree = false; |
477 | | |
478 | | // Insert at the end a new segment with the initial base value, for |
479 | | // the length of the removed segment. |
480 | | append_new_segment(right_leaf_key - segment_size); |
481 | | } |
482 | | |
483 | | template<typename Key, typename Value> |
484 | | void flat_segment_tree<Key, Value>::shift_right(key_type pos, key_type size, bool skip_start_node) |
485 | | { |
486 | | if (size <= 0) |
487 | | return; |
488 | | |
489 | | if (pos < m_left_leaf->key || m_right_leaf->key <= pos) |
490 | | // specified position is out-of-bound |
491 | | return; |
492 | | |
493 | | if (m_left_leaf->key == pos) |
494 | | { |
495 | | // Position is at the leftmost node. Shift all the other nodes, |
496 | | // and insert a new node at (pos + size) position. |
497 | | node_ptr cur_node = m_left_leaf->next; |
498 | | shift_leaf_key_right(cur_node, m_right_leaf, size); |
499 | | |
500 | | if (m_left_leaf->value_leaf.value != m_init_val && !skip_start_node) |
501 | | { |
502 | | if (size < m_right_leaf->key - m_left_leaf->key) |
503 | | { |
504 | | // The leftmost leaf node has a non-initial value. We need to |
505 | | // insert a new node to carry that value after the shift. |
506 | | node_ptr new_node(new node); |
507 | | new_node->key = pos + size; |
508 | | new_node->value_leaf.value = m_left_leaf->value_leaf.value; |
509 | | m_left_leaf->value_leaf.value = m_init_val; |
510 | | new_node->prev = m_left_leaf; |
511 | | new_node->next = m_left_leaf->next; |
512 | | m_left_leaf->next->prev = new_node; |
513 | | m_left_leaf->next = std::move(new_node); |
514 | | } |
515 | | else |
516 | | { |
517 | | // We shifted out the whole range, so there would be no new |
518 | | // node inserted. Just set default value. |
519 | | m_left_leaf->value_leaf.value = m_init_val; |
520 | | } |
521 | | } |
522 | | |
523 | | m_valid_tree = false; |
524 | | return; |
525 | | } |
526 | | |
527 | | // Get the first node with a key value equal to or greater than the |
528 | | // start key value. But we want to skip the leftmost node. |
529 | | const node* p = get_insertion_pos_leaf(pos, m_left_leaf->next.get()); |
530 | | node_ptr cur_node(const_cast<node*>(p)); |
531 | | |
532 | | // If the point of insertion is at an existing node position, don't |
533 | | // shift that node but start with the one after it if that's |
534 | | // requested. |
535 | | if (skip_start_node && cur_node && cur_node->key == pos) |
536 | | cur_node = cur_node->next; |
537 | | |
538 | | if (!cur_node) |
539 | | return; |
540 | | |
541 | | shift_leaf_key_right(cur_node, m_right_leaf, size); |
542 | | m_valid_tree = false; |
543 | | } |
544 | | |
545 | | template<typename Key, typename Value> |
546 | | ::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search_impl( |
547 | | const node* pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const |
548 | | { |
549 | | typedef ::std::pair<const_iterator, bool> ret_type; |
550 | | |
551 | | if (pos->key == key) |
552 | | { |
553 | | value = pos->value_leaf.value; |
554 | | if (start_key) |
555 | | *start_key = pos->key; |
556 | | if (end_key && pos->next) |
557 | | *end_key = pos->next->key; |
558 | | return ret_type(const_iterator(this, pos), true); |
559 | | } |
560 | | else if (pos->prev && pos->prev->key < key) |
561 | | { |
562 | | value = pos->prev->value_leaf.value; |
563 | | if (start_key) |
564 | | *start_key = pos->prev->key; |
565 | | if (end_key) |
566 | | *end_key = pos->key; |
567 | | return ret_type(const_iterator(this, pos->prev.get()), true); |
568 | | } |
569 | | |
570 | | return ret_type(const_iterator(this, true), false); |
571 | | } |
572 | | |
573 | | template<typename Key, typename Value> |
574 | | ::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search( |
575 | | key_type key, value_type& value, key_type* start_key, key_type* end_key) const |
576 | | { |
577 | | typedef ::std::pair<const_iterator, bool> ret_type; |
578 | | |
579 | | if (key < m_left_leaf->key || m_right_leaf->key <= key) |
580 | | // key value is out-of-bound. |
581 | | return ret_type(const_iterator(this, true), false); |
582 | | |
583 | | const node* pos = get_insertion_pos_leaf(key, m_left_leaf.get()); |
584 | | return search_impl(pos, key, value, start_key, end_key); |
585 | | } |
586 | | |
587 | | template<typename Key, typename Value> |
588 | | ::std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search( |
589 | | const_iterator pos, key_type key, value_type& value, key_type* start_key, key_type* end_key) const |
590 | | { |
591 | | typedef ::std::pair<const_iterator, bool> ret_type; |
592 | | |
593 | | if (key < m_left_leaf->key || m_right_leaf->key <= key) |
594 | | // key value is out-of-bound. |
595 | | return ret_type(const_iterator(this, true), false); |
596 | | |
597 | | const node* p = pos.get_pos(); |
598 | | if (!p || this != pos.get_parent()) |
599 | | { |
600 | | // Switch to normal search. |
601 | | return search(key, value, start_key, end_key); |
602 | | } |
603 | | |
604 | | assert(p->is_leaf); |
605 | | |
606 | | if (key < p->key) |
607 | | { |
608 | | // Specified position is already past the start key position. Fall |
609 | | // back to normal search. |
610 | | return search(key, value, start_key, end_key); |
611 | | } |
612 | | |
613 | | p = get_insertion_pos_leaf(key, p); |
614 | | return search_impl(p, key, value, start_key, end_key); |
615 | | } |
616 | | |
617 | | template<typename Key, typename Value> |
618 | | typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search(key_type key) const |
619 | | { |
620 | | return search_by_key_impl(m_left_leaf.get(), key); |
621 | | } |
622 | | |
623 | | template<typename Key, typename Value> |
624 | | typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search( |
625 | | const_iterator pos, key_type key) const |
626 | | { |
627 | | return search_by_key_impl(pos.get_pos(), key); |
628 | | } |
629 | | |
630 | | template<typename Key, typename Value> |
631 | | typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search_by_key_impl( |
632 | | const node* start_pos, key_type key) const |
633 | | { |
634 | | if (key < m_left_leaf->key || m_right_leaf->key <= key) |
635 | | // key value is out-of-bound. |
636 | | return const_iterator(this, true); |
637 | | |
638 | | const node* pos = get_insertion_pos_leaf(key, start_pos); |
639 | | if (!pos) |
640 | | return const_iterator(this, true); |
641 | | |
642 | | if (pos->key == key) |
643 | | return const_iterator(this, pos); |
644 | | else if (pos->prev && pos->prev->key < key) |
645 | | return const_iterator(this, pos->prev.get()); |
646 | | |
647 | | return const_iterator(this, true); |
648 | | } |
649 | | |
650 | | template<typename Key, typename Value> |
651 | | std::pair<typename flat_segment_tree<Key, Value>::const_iterator, bool> flat_segment_tree<Key, Value>::search_tree( |
652 | | key_type key, value_type& value, key_type* start_key, key_type* end_key) const |
653 | 728 | { |
654 | 728 | using ret_type = std::pair<const_iterator, bool>; |
655 | | |
656 | 728 | const node* dest_node = search_tree_for_leaf_node(key); |
657 | 728 | if (!dest_node) |
658 | 0 | return ret_type(const_iterator(this, true), false); |
659 | | |
660 | 728 | value = dest_node->value_leaf.value; |
661 | 728 | if (start_key) |
662 | 0 | *start_key = dest_node->key; |
663 | | |
664 | 728 | if (end_key) |
665 | 0 | { |
666 | 0 | assert(dest_node->next); |
667 | 0 | if (dest_node->next) |
668 | 0 | *end_key = dest_node->next->key; |
669 | 0 | else |
670 | | // This should never happen, but just in case.... |
671 | 0 | *end_key = m_right_leaf->key; |
672 | 0 | } |
673 | | |
674 | 728 | return ret_type(const_iterator(this, dest_node), true); |
675 | 728 | } |
676 | | |
677 | | template<typename Key, typename Value> |
678 | | typename flat_segment_tree<Key, Value>::const_iterator flat_segment_tree<Key, Value>::search_tree(key_type key) const |
679 | | { |
680 | | const node* dest_node = search_tree_for_leaf_node(key); |
681 | | if (!dest_node) |
682 | | return const_iterator(this, true); |
683 | | |
684 | | return const_iterator(this, dest_node); |
685 | | } |
686 | | |
687 | | template<typename Key, typename Value> |
688 | | const typename flat_segment_tree<Key, Value>::node* flat_segment_tree<Key, Value>::search_tree_for_leaf_node( |
689 | | key_type key) const |
690 | 728 | { |
691 | 728 | if (!m_root_node || !m_valid_tree) |
692 | 0 | { |
693 | | // either tree has not been built, or is in an invalid state. |
694 | 0 | return nullptr; |
695 | 0 | } |
696 | | |
697 | 728 | if (key < m_left_leaf->key || m_right_leaf->key <= key) |
698 | 0 | { |
699 | | // key value is out-of-bound. |
700 | 0 | return nullptr; |
701 | 0 | } |
702 | | |
703 | | // Descend down the tree through the last non-leaf layer. |
704 | | |
705 | 728 | const nonleaf_node* cur_node = m_root_node; |
706 | 1.44k | while (true) |
707 | 1.44k | { |
708 | 1.44k | if (cur_node->left) |
709 | 1.44k | { |
710 | 1.44k | if (cur_node->left->is_leaf) |
711 | 728 | break; |
712 | | |
713 | 714 | const nonleaf_node* left_nonleaf = static_cast<const nonleaf_node*>(cur_node->left); |
714 | 714 | if (left_nonleaf->low <= key && key < left_nonleaf->high) |
715 | 376 | { |
716 | | // Descend one level through the left child node. |
717 | 376 | cur_node = left_nonleaf; |
718 | 376 | continue; |
719 | 376 | } |
720 | 714 | } |
721 | 0 | else |
722 | 0 | { |
723 | | // left child node can't be missing ! |
724 | 0 | return nullptr; |
725 | 0 | } |
726 | | |
727 | 338 | if (cur_node->right) |
728 | 338 | { |
729 | 338 | assert(!cur_node->right->is_leaf); |
730 | 338 | const nonleaf_node* right_nonleaf = static_cast<const nonleaf_node*>(cur_node->right); |
731 | 338 | if (right_nonleaf->low <= key && key < right_nonleaf->high) |
732 | 338 | { |
733 | | // Descend one level through the right child node. |
734 | 338 | cur_node = right_nonleaf; |
735 | 338 | continue; |
736 | 338 | } |
737 | 338 | } |
738 | 0 | return nullptr; |
739 | 338 | } |
740 | | |
741 | | // Current node must be a non-leaf whose child nodes are leaf nodes. |
742 | 728 | assert(cur_node->left->is_leaf && cur_node->right->is_leaf); |
743 | | |
744 | 728 | const node* dest_node = nullptr; |
745 | 728 | const node* leaf_left = static_cast<const node*>(cur_node->left); |
746 | 728 | const node* leaf_right = static_cast<const node*>(cur_node->right); |
747 | 728 | key_type key1 = leaf_left->key; |
748 | 728 | key_type key2 = leaf_right->key; |
749 | | |
750 | 728 | if (key1 <= key && key < key2) |
751 | 602 | { |
752 | 602 | dest_node = leaf_left; |
753 | 602 | } |
754 | 126 | else if (key2 <= key && key < cur_node->high) |
755 | 126 | { |
756 | 126 | dest_node = leaf_right; |
757 | 126 | } |
758 | | |
759 | 728 | if (!dest_node) |
760 | 0 | return nullptr; |
761 | | |
762 | 728 | return dest_node; |
763 | 728 | } |
764 | | |
765 | | template<typename Key, typename Value> |
766 | | void flat_segment_tree<Key, Value>::build_tree() |
767 | 129 | { |
768 | 129 | if (!m_left_leaf) |
769 | 0 | return; |
770 | | |
771 | 129 | m_nonleaf_node_pool.clear(); |
772 | | |
773 | | // Count the number of leaf nodes. |
774 | 129 | size_t leaf_count = leaf_size(); |
775 | | |
776 | | // Determine the total number of non-leaf nodes needed to build the whole tree. |
777 | 129 | size_t nonleaf_count = st::detail::count_needed_nonleaf_nodes(leaf_count); |
778 | | |
779 | 129 | m_nonleaf_node_pool.resize(nonleaf_count); |
780 | 129 | mdds::st::detail::tree_builder<flat_segment_tree> builder(m_nonleaf_node_pool); |
781 | 129 | m_root_node = builder.build(m_left_leaf); |
782 | 129 | m_valid_tree = true; |
783 | 129 | } |
784 | | |
785 | | template<typename Key, typename Value> |
786 | | typename flat_segment_tree<Key, Value>::size_type flat_segment_tree<Key, Value>::leaf_size() const |
787 | 129 | { |
788 | 129 | return st::detail::count_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); |
789 | 129 | } |
790 | | |
791 | | template<typename Key, typename Value> |
792 | | bool flat_segment_tree<Key, Value>::operator==(const flat_segment_tree& other) const |
793 | | { |
794 | | const node* n1 = m_left_leaf.get(); |
795 | | const node* n2 = other.m_left_leaf.get(); |
796 | | |
797 | | if ((!n1 && n2) || (n1 && !n2)) |
798 | | // Either one of them is nullptr; |
799 | | return false; |
800 | | |
801 | | while (n1) |
802 | | { |
803 | | if (!n2) |
804 | | return false; |
805 | | |
806 | | if (n1->key != n2->key) |
807 | | return false; |
808 | | |
809 | | if (n1->value_leaf != n2->value_leaf) |
810 | | return false; |
811 | | |
812 | | n1 = n1->next.get(); |
813 | | n2 = n2->next.get(); |
814 | | } |
815 | | |
816 | | if (n2) |
817 | | // n1 is nullptr, but n2 is not. |
818 | | return false; |
819 | | |
820 | | // All leaf nodes are equal. |
821 | | return true; |
822 | | } |
823 | | |
824 | | template<typename Key, typename Value> |
825 | | const typename flat_segment_tree<Key, Value>::node* flat_segment_tree<Key, Value>::get_insertion_pos_leaf_reverse( |
826 | | const key_type& key, const node* start_pos) const |
827 | 1.44k | { |
828 | 1.44k | const node* cur_node = start_pos; |
829 | 3.69k | while (cur_node) |
830 | 3.37k | { |
831 | 3.37k | if (cur_node->key < key) |
832 | 1.11k | { |
833 | | // Found the insertion position. |
834 | 1.11k | return cur_node; |
835 | 1.11k | } |
836 | 2.25k | cur_node = cur_node->prev.get(); |
837 | 2.25k | } |
838 | 326 | return nullptr; |
839 | 1.44k | } mdds::flat_segment_tree<unsigned int, float>::get_insertion_pos_leaf_reverse(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> const*) const Line | Count | Source | 827 | 656 | { | 828 | 656 | const node* cur_node = start_pos; | 829 | 1.96k | while (cur_node) | 830 | 1.80k | { | 831 | 1.80k | if (cur_node->key < key) | 832 | 492 | { | 833 | | // Found the insertion position. | 834 | 492 | return cur_node; | 835 | 492 | } | 836 | 1.31k | cur_node = cur_node->prev.get(); | 837 | 1.31k | } | 838 | 164 | return nullptr; | 839 | 656 | } |
mdds::flat_segment_tree<unsigned int, bool>::get_insertion_pos_leaf_reverse(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> const*) const Line | Count | Source | 827 | 651 | { | 828 | 651 | const node* cur_node = start_pos; | 829 | 1.46k | while (cur_node) | 830 | 1.30k | { | 831 | 1.30k | if (cur_node->key < key) | 832 | 489 | { | 833 | | // Found the insertion position. | 834 | 489 | return cur_node; | 835 | 489 | } | 836 | 813 | cur_node = cur_node->prev.get(); | 837 | 813 | } | 838 | 162 | return nullptr; | 839 | 651 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::get_insertion_pos_leaf_reverse(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> const*) const Line | Count | Source | 827 | 133 | { | 828 | 133 | const node* cur_node = start_pos; | 829 | 266 | while (cur_node) | 830 | 266 | { | 831 | 266 | if (cur_node->key < key) | 832 | 133 | { | 833 | | // Found the insertion position. | 834 | 133 | return cur_node; | 835 | 133 | } | 836 | 133 | cur_node = cur_node->prev.get(); | 837 | 133 | } | 838 | 0 | return nullptr; | 839 | 133 | } |
|
840 | | |
841 | | template<typename Key, typename Value> |
842 | | const typename flat_segment_tree<Key, Value>::node* flat_segment_tree<Key, Value>::get_insertion_pos_leaf( |
843 | | const key_type& key, const node* start_pos) const |
844 | 1.44k | { |
845 | 1.44k | assert(m_left_leaf->key <= key); |
846 | | |
847 | 1.44k | const node* cur_node = start_pos; |
848 | 2.25k | while (cur_node) |
849 | 2.25k | { |
850 | 2.25k | if (key <= cur_node->key) |
851 | 1.44k | { |
852 | | // Found the insertion position. |
853 | 1.44k | return cur_node; |
854 | 1.44k | } |
855 | 817 | cur_node = cur_node->next.get(); |
856 | 817 | } |
857 | 0 | return nullptr; |
858 | 1.44k | } mdds::flat_segment_tree<unsigned int, float>::get_insertion_pos_leaf(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> const*) const Line | Count | Source | 844 | 656 | { | 845 | 656 | assert(m_left_leaf->key <= key); | 846 | | | 847 | 656 | const node* cur_node = start_pos; | 848 | 1.31k | while (cur_node) | 849 | 1.31k | { | 850 | 1.31k | if (key <= cur_node->key) | 851 | 656 | { | 852 | | // Found the insertion position. | 853 | 656 | return cur_node; | 854 | 656 | } | 855 | 655 | cur_node = cur_node->next.get(); | 856 | 655 | } | 857 | 0 | return nullptr; | 858 | 656 | } |
mdds::flat_segment_tree<unsigned int, bool>::get_insertion_pos_leaf(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> const*) const Line | Count | Source | 844 | 651 | { | 845 | 651 | assert(m_left_leaf->key <= key); | 846 | | | 847 | 651 | const node* cur_node = start_pos; | 848 | 813 | while (cur_node) | 849 | 813 | { | 850 | 813 | if (key <= cur_node->key) | 851 | 651 | { | 852 | | // Found the insertion position. | 853 | 651 | return cur_node; | 854 | 651 | } | 855 | 162 | cur_node = cur_node->next.get(); | 856 | 162 | } | 857 | 0 | return nullptr; | 858 | 651 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::get_insertion_pos_leaf(unsigned int const&, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> const*) const Line | Count | Source | 844 | 133 | { | 845 | 133 | assert(m_left_leaf->key <= key); | 846 | | | 847 | 133 | const node* cur_node = start_pos; | 848 | 133 | while (cur_node) | 849 | 133 | { | 850 | 133 | if (key <= cur_node->key) | 851 | 133 | { | 852 | | // Found the insertion position. | 853 | 133 | return cur_node; | 854 | 133 | } | 855 | 0 | cur_node = cur_node->next.get(); | 856 | 0 | } | 857 | 0 | return nullptr; | 858 | 133 | } |
|
859 | | |
860 | | template<typename Key, typename Value> |
861 | | void flat_segment_tree<Key, Value>::destroy() |
862 | 971 | { |
863 | 971 | disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); |
864 | 971 | m_nonleaf_node_pool.clear(); |
865 | 971 | m_root_node = nullptr; |
866 | 971 | } mdds::flat_segment_tree<unsigned int, bool>::destroy() Line | Count | Source | 862 | 212 | { | 863 | 212 | disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); | 864 | 212 | m_nonleaf_node_pool.clear(); | 865 | 212 | m_root_node = nullptr; | 866 | 212 | } |
mdds::flat_segment_tree<unsigned int, float>::destroy() Line | Count | Source | 862 | 212 | { | 863 | 212 | disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); | 864 | 212 | m_nonleaf_node_pool.clear(); | 865 | 212 | m_root_node = nullptr; | 866 | 212 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::destroy() Line | Count | Source | 862 | 547 | { | 863 | 547 | disconnect_leaf_nodes(m_left_leaf.get(), m_right_leaf.get()); | 864 | 547 | m_nonleaf_node_pool.clear(); | 865 | 547 | m_root_node = nullptr; | 866 | 547 | } |
|
867 | | |
868 | | template<typename Key, typename Value> |
869 | | bool flat_segment_tree<Key, Value>::adjust_segment_range(key_type& start_key, key_type& end_key) const |
870 | 1.44k | { |
871 | 1.44k | if (end_key <= start_key) |
872 | | // Invalid order of segment range. |
873 | 0 | return false; |
874 | | |
875 | 1.44k | if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key) |
876 | | // The new segment does not overlap the current interval. |
877 | 0 | return false; |
878 | | |
879 | 1.44k | if (start_key < m_left_leaf->key) |
880 | | // The start value should not be smaller than the current minimum. |
881 | 0 | start_key = m_left_leaf->key; |
882 | | |
883 | 1.44k | if (m_right_leaf->key < end_key) |
884 | | // The end value should not be larger than the current maximum. |
885 | 0 | end_key = m_right_leaf->key; |
886 | | |
887 | 1.44k | return true; |
888 | 1.44k | } mdds::flat_segment_tree<unsigned int, float>::adjust_segment_range(unsigned int&, unsigned int&) const Line | Count | Source | 870 | 656 | { | 871 | 656 | if (end_key <= start_key) | 872 | | // Invalid order of segment range. | 873 | 0 | return false; | 874 | | | 875 | 656 | if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key) | 876 | | // The new segment does not overlap the current interval. | 877 | 0 | return false; | 878 | | | 879 | 656 | if (start_key < m_left_leaf->key) | 880 | | // The start value should not be smaller than the current minimum. | 881 | 0 | start_key = m_left_leaf->key; | 882 | | | 883 | 656 | if (m_right_leaf->key < end_key) | 884 | | // The end value should not be larger than the current maximum. | 885 | 0 | end_key = m_right_leaf->key; | 886 | | | 887 | 656 | return true; | 888 | 656 | } |
mdds::flat_segment_tree<unsigned int, bool>::adjust_segment_range(unsigned int&, unsigned int&) const Line | Count | Source | 870 | 651 | { | 871 | 651 | if (end_key <= start_key) | 872 | | // Invalid order of segment range. | 873 | 0 | return false; | 874 | | | 875 | 651 | if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key) | 876 | | // The new segment does not overlap the current interval. | 877 | 0 | return false; | 878 | | | 879 | 651 | if (start_key < m_left_leaf->key) | 880 | | // The start value should not be smaller than the current minimum. | 881 | 0 | start_key = m_left_leaf->key; | 882 | | | 883 | 651 | if (m_right_leaf->key < end_key) | 884 | | // The end value should not be larger than the current maximum. | 885 | 0 | end_key = m_right_leaf->key; | 886 | | | 887 | 651 | return true; | 888 | 651 | } |
mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::adjust_segment_range(unsigned int&, unsigned int&) const Line | Count | Source | 870 | 133 | { | 871 | 133 | if (end_key <= start_key) | 872 | | // Invalid order of segment range. | 873 | 0 | return false; | 874 | | | 875 | 133 | if (end_key < m_left_leaf->key || m_right_leaf->key <= start_key) | 876 | | // The new segment does not overlap the current interval. | 877 | 0 | return false; | 878 | | | 879 | 133 | if (start_key < m_left_leaf->key) | 880 | | // The start value should not be smaller than the current minimum. | 881 | 0 | start_key = m_left_leaf->key; | 882 | | | 883 | 133 | if (m_right_leaf->key < end_key) | 884 | | // The end value should not be larger than the current maximum. | 885 | 0 | end_key = m_right_leaf->key; | 886 | | | 887 | 133 | return true; | 888 | 133 | } |
|
889 | | |
890 | | } // namespace mdds |