update dev300-m57
[ooovba.git] / sc / inc / mdds / flatsegmenttree.hxx
blob96a6256d3a7777bde6b077433bebd69f7d616082
1 /*************************************************************************
3 * Copyright (c) 2008-2009 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:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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.
26 ************************************************************************/
28 #ifndef __MDDS_FLATSEGMENTTREE_HXX__
29 #define __MDDS_FLATSEGMENTTREE_HXX__
31 #include <iostream>
32 #include <cassert>
34 #include "node.hxx"
36 #ifdef UNIT_TEST
37 #include <vector>
38 #endif
40 namespace mdds {
42 template<typename _Key, typename _Value>
43 class flat_segment_tree
45 public:
46 typedef _Key key_type;
47 typedef _Value value_type;
49 struct nonleaf_value_type
51 key_type low; /// low range value (inclusive)
52 key_type high; /// high range value (non-inclusive)
55 struct leaf_value_type
57 key_type key;
58 value_type value;
61 struct node : public node_base
63 union {
64 nonleaf_value_type value_nonleaf;
65 leaf_value_type value_leaf;
68 node(bool _is_leaf) :
69 node_base(_is_leaf)
73 virtual ~node()
77 virtual void fill_nonleaf_value(const node_base_ptr& left_node, const node_base_ptr& right_node)
79 // Parent node should carry the range of all of its child nodes.
80 if (left_node)
81 value_nonleaf.low = left_node->is_leaf ? get_node(left_node)->value_leaf.key : get_node(left_node)->value_nonleaf.low;
82 else
83 // Having a left node is prerequisite.
84 return;
86 if (right_node)
88 if (right_node->is_leaf)
90 // When the child nodes are leaf nodes, the upper bound
91 // must be the value of the node that comes after the
92 // right leaf node (if such node exists).
94 if (right_node->right)
95 value_nonleaf.high = get_node(right_node->right)->value_leaf.key;
96 else
97 value_nonleaf.high = get_node(right_node)->value_leaf.key;
99 else
101 value_nonleaf.high = get_node(right_node)->value_nonleaf.high;
104 else
105 value_nonleaf.high = left_node->is_leaf ? get_node(left_node)->value_leaf.key : get_node(left_node)->value_nonleaf.high;
108 virtual void dump_value() const
110 using ::std::cout;
111 if (is_leaf)
113 cout << "(" << value_leaf.key << ")";
115 else
117 cout << "(" << value_nonleaf.low << "-" << value_nonleaf.high << ")";
119 cout << " ";
122 virtual node_base* create_new(bool leaf) const
124 return new node(leaf);
128 /**
129 * Get a pointer of concrete node type from the base pointer.
131 * @param base_node base node pointer (ref-counted)
133 * @return raw pointer of concrete node type
135 static node* get_node(const node_base_ptr& base_node)
137 return static_cast<node*>(base_node.get());
140 flat_segment_tree(key_type min_val, key_type max_val, value_type init_val) :
141 m_root_node(static_cast<node*>(NULL)),
142 m_left_leaf(new node(true)),
143 m_right_leaf(new node(true)),
144 m_init_val(init_val),
145 m_valid_tree(false)
147 // we need to create two end nodes during initialization.
148 get_node(m_left_leaf)->value_leaf.key = min_val;
149 get_node(m_left_leaf)->value_leaf.value = init_val;
150 m_left_leaf->right = m_right_leaf;
152 get_node(m_right_leaf)->value_leaf.key = max_val;
153 m_right_leaf->left = m_left_leaf;
156 ~flat_segment_tree()
158 // Go through all leaf nodes, and disconnect their links.
159 node_base* cur_node = m_left_leaf.get();
162 node_base* next_node = cur_node->right.get();
163 disconnect_node(cur_node);
164 cur_node = next_node;
166 while (cur_node != m_right_leaf.get());
168 disconnect_node(m_right_leaf.get());
169 clear_tree(m_root_node);
170 disconnect_node(m_root_node.get());
173 /**
174 * Insert a new segment into the tree.
176 * @param start start value of the segment being inserted. The value is
177 * inclusive.
178 * @param end end value of the segment being inserted. The value is not
179 * inclusive.
180 * @param val value associated with this segment.
182 void insert_segment(key_type start, key_type end, value_type val)
184 if (end < get_node(m_left_leaf)->value_leaf.key || start > get_node(m_right_leaf)->value_leaf.key)
185 // The new segment does not overlap the current interval.
186 return;
188 if (start < get_node(m_left_leaf)->value_leaf.key)
189 // The start value should not be smaller than the current minimum.
190 start = get_node(m_left_leaf)->value_leaf.key;
192 if (end > get_node(m_right_leaf)->value_leaf.key)
193 // The end value should not be larger than the current maximum.
194 end = get_node(m_right_leaf)->value_leaf.key;
196 if (start >= end)
197 return;
199 // Find the node with value that either equals or is greater than the
200 // start value.
202 node_base_ptr start_pos = get_insertion_pos_leaf(start, m_left_leaf);
203 if (!start_pos)
204 // Insertion position not found. Bail out.
205 return;
207 node_base_ptr end_pos = get_insertion_pos_leaf(end, start_pos);
208 if (!end_pos)
209 end_pos = m_right_leaf;
211 node_base_ptr new_start_node;
212 value_type old_value;
214 // Set the start node.
216 if (get_node(start_pos)->value_leaf.key == start)
218 // Re-use the existing node, but save the old value for later.
220 if (start_pos->left && get_node(start_pos->left)->value_leaf.value == val)
222 // Extend the existing segment.
223 old_value = get_node(start_pos)->value_leaf.value;
224 new_start_node = start_pos->left;
226 else
228 // Update the value of the existing node.
229 old_value = get_node(start_pos)->value_leaf.value;
230 get_node(start_pos)->value_leaf.value = val;
231 new_start_node = start_pos;
234 else if (get_node(start_pos->left)->value_leaf.value == val)
236 // Extend the existing segment.
237 old_value = get_node(start_pos->left)->value_leaf.value;
238 new_start_node = start_pos->left;
240 else
242 // Insert a new node before the insertion position node.
243 node_base_ptr new_node(new node(true));
244 get_node(new_node)->value_leaf.key = start;
245 get_node(new_node)->value_leaf.value = val;
246 new_start_node = new_node;
248 node_base_ptr left_node = start_pos->left;
249 old_value = get_node(left_node)->value_leaf.value;
251 // Link to the left node.
252 link_nodes(left_node, new_node);
254 // Link to the right node.
255 link_nodes(new_node, start_pos);
258 node_base_ptr cur_node = new_start_node->right;
259 while (cur_node != end_pos)
261 // Disconnect the link between the current node and the previous node.
262 cur_node->left->right.reset();
263 cur_node->left.reset();
264 old_value = get_node(cur_node)->value_leaf.value;
266 cur_node = cur_node->right;
269 // Set the end node.
271 if (get_node(end_pos)->value_leaf.key == end)
273 // The new segment ends exactly at the end node position.
275 if (end_pos->right && get_node(end_pos)->value_leaf.value == val)
277 // Remove this node, and connect the new start node with the
278 // node that comes after this node.
279 new_start_node->right = end_pos->right;
280 if (end_pos->right)
281 end_pos->right->left = new_start_node;
282 disconnect_node(end_pos.get());
284 else
286 // Just link the new segment to this node.
287 new_start_node->right = end_pos;
288 end_pos->left = new_start_node;
291 else if (old_value == val)
293 link_nodes(new_start_node, end_pos);
295 else
297 // Insert a new node before the insertion position node.
298 node_base_ptr new_node(new node(true));
299 get_node(new_node)->value_leaf.key = end;
300 get_node(new_node)->value_leaf.value = old_value;
302 // Link to the left node.
303 link_nodes(new_start_node, new_node);
305 // Link to the right node.
306 link_nodes(new_node, end_pos);
309 m_valid_tree = false;
312 /**
313 * Remove a segment specified by the start and end key values, and shift
314 * the remaining segments (i.e. those segments that come after the removed
315 * segment) to left.
317 * @param start start value of the segment being removed.
318 * @param end end value of the segment being removed.
320 void shift_segment_left(key_type start, key_type end)
322 if (start >= end)
323 return;
325 key_type left_leaf_key = get_node(m_left_leaf)->value_leaf.key;
326 key_type right_leaf_key = get_node(m_right_leaf)->value_leaf.key;
327 if (start < left_leaf_key || end < left_leaf_key)
328 // invalid key value
329 return;
331 if (start > right_leaf_key || end > right_leaf_key)
332 // invalid key value.
333 return;
335 node_base_ptr node_pos;
336 if (left_leaf_key == start)
337 node_pos = m_left_leaf;
338 else
339 // Get the first node with a key value equal to or greater than the
340 // start key value. But we want to skip the leftmost node.
341 node_pos = get_insertion_pos_leaf(start, m_left_leaf->right);
343 if (!node_pos)
344 return;
346 key_type segment_size = end - start;
348 if (end < get_node(node_pos)->value_leaf.key)
350 // The removed segment does not overlap with any nodes. Simply
351 // shift the key values of those nodes that come after the removed
352 // segment.
353 shift_leaf_key_left(node_pos, m_right_leaf, segment_size);
354 m_valid_tree = false;
355 return;
358 // Move the first node to the starting position, and from there search
359 // for the first node whose key value is greater than the end value.
360 get_node(node_pos)->value_leaf.key = start;
361 node_base_ptr start_pos = node_pos;
362 node_pos = node_pos->right;
363 value_type last_seg_value = get_node(start_pos)->value_leaf.value;
364 while (get_node(node_pos) != get_node(m_right_leaf) && get_node(node_pos)->value_leaf.key <= end)
366 last_seg_value = get_node(node_pos)->value_leaf.value;
367 node_base_ptr next = node_pos->right;
368 disconnect_node(node_pos.get());
369 node_pos = next;
372 get_node(start_pos)->value_leaf.value = last_seg_value;
373 start_pos->right = node_pos;
374 node_pos->left = start_pos;
375 if (start_pos->left && get_node(start_pos->left)->value_leaf.value == get_node(start_pos)->value_leaf.value)
377 // Removing a segment resulted in two consecutive segments with
378 // identical value. Combine them by removing the 2nd redundant
379 // node.
380 start_pos->left->right = start_pos->right;
381 start_pos->right->left = start_pos->left;
382 disconnect_node(start_pos.get());
385 shift_leaf_key_left(node_pos, m_right_leaf, segment_size);
386 m_valid_tree = false;
389 /**
390 * Shift all segments that occur at or after the specified start position
391 * to right by the size specified.
393 * @param pos position where the right-shift occurs.
394 * @param size amount of shift (must be greater than 0)
396 void shift_segment_right(key_type pos, key_type size, bool skip_start_node)
398 if (size <= 0)
399 return;
401 if (pos < get_node(m_left_leaf)->value_leaf.key || get_node(m_right_leaf)->value_leaf.key <= pos)
402 // specified position is out-of-bound
403 return;
405 if (get_node(m_left_leaf)->value_leaf.key == pos)
407 // Position is at the leftmost node. Shift all the other nodes,
408 // and insert a new node at (pos + size) position.
409 node_base_ptr cur_node = m_left_leaf->right;
410 shift_leaf_key_right(cur_node, m_right_leaf, size);
412 if (get_node(m_left_leaf)->value_leaf.value != m_init_val)
414 // The leftmost leaf node has a non-initial value. We need to
415 // insert a new node to carry that value after the shift.
416 node_base_ptr new_node(new node(true));
417 get_node(new_node)->value_leaf.key = pos + size;
418 get_node(new_node)->value_leaf.value = get_node(m_left_leaf)->value_leaf.value;
419 get_node(m_left_leaf)->value_leaf.value = m_init_val;
420 new_node->left = m_left_leaf;
421 new_node->right = m_left_leaf->right;
422 m_left_leaf->right = new_node;
425 m_valid_tree = false;
426 return;
429 // Get the first node with a key value equal to or greater than the
430 // start key value. But we want to skip the leftmost node.
431 node_base_ptr cur_node = get_insertion_pos_leaf(pos, m_left_leaf->right);
433 // If the point of insertion is at an existing node position, don't
434 // shift that node but start with the one after it if that's
435 // requested.
436 if (skip_start_node && cur_node && get_node(cur_node)->value_leaf.key == pos)
437 cur_node = cur_node->right;
439 if (!cur_node)
440 return;
442 shift_leaf_key_right(cur_node, m_right_leaf, size);
443 m_valid_tree = false;
446 bool search(key_type key, value_type& value, key_type* start = NULL, key_type* end = NULL) const
448 if (key < get_node(m_left_leaf)->value_leaf.key || get_node(m_right_leaf)->value_leaf.key <= key)
449 // key value is out-of-bound.
450 return false;
452 const node* pos = get_insertion_pos_leaf(key, get_node(m_left_leaf));
453 if (pos->value_leaf.key == key)
455 value = pos->value_leaf.value;
456 if (start)
457 *start = pos->value_leaf.key;
458 if (end && pos->right)
459 *end = get_node(pos->right)->value_leaf.key;
460 return true;
462 else if (pos->left && get_node(pos->left)->value_leaf.key < key)
464 value = get_node(pos->left)->value_leaf.value;
465 if (start)
466 *start = get_node(pos->left)->value_leaf.key;
467 if (end)
468 *end = pos->value_leaf.key;
469 return true;
472 return false;
475 bool search_tree(key_type key, value_type& value, key_type* start = NULL, key_type* end = NULL) const
477 if (!m_root_node || !m_valid_tree)
479 // either tree has not been built, or is in an invalid state.
480 return false;
483 if (key < get_node(m_left_leaf)->value_leaf.key || get_node(m_right_leaf)->value_leaf.key <= key)
485 // key value is out-of-bound.
486 return false;
489 // Descend down the tree through the last non-leaf layer.
491 node* cur_node = get_node(m_root_node);
492 while (true)
494 if (cur_node->left)
496 if (cur_node->left->is_leaf)
497 break;
499 const nonleaf_value_type& v = get_node(cur_node->left)->value_nonleaf;
500 if (v.low <= key && key < v.high)
502 cur_node = get_node(cur_node->left);
503 continue;
506 else
508 // left child node can't be missing !
509 return false;
512 if (cur_node->right)
514 const nonleaf_value_type& v = get_node(cur_node->right)->value_nonleaf;
515 if (v.low <= key && key < v.high)
517 cur_node = get_node(cur_node->right);
518 continue;
521 return false;
524 assert(cur_node->left->is_leaf && cur_node->right->is_leaf);
526 key_type key1 = get_node(cur_node->left)->value_leaf.key;
527 key_type key2 = get_node(cur_node->right)->value_leaf.key;
529 if (key1 <= key && key < key2)
531 cur_node = get_node(cur_node->left);
533 else if (key2 <= key && key < cur_node->value_nonleaf.high)
535 cur_node = get_node(cur_node->right);
537 else
538 cur_node = NULL;
540 if (!cur_node)
542 return false;
545 value = cur_node->value_leaf.value;
546 if (start)
547 *start = cur_node->value_leaf.key;
549 if (end)
551 assert(cur_node->right);
552 if (cur_node->right)
553 *end = get_node(cur_node->right)->value_leaf.key;
554 else
555 // This should never happen, but just in case....
556 *end = get_node(m_right_leaf)->value_leaf.key;
559 return true;
562 void build_tree()
564 if (!m_left_leaf)
565 return;
567 clear_tree(m_root_node);
568 m_root_node = ::mdds::build_tree(m_left_leaf);
569 m_valid_tree = true;
572 bool is_tree_valid() const
574 return m_valid_tree;
577 #ifdef UNIT_TEST
578 void dump_tree() const
580 using ::std::cout;
581 using ::std::endl;
583 if (!m_valid_tree)
584 assert(!"attempted to dump an invalid tree!");
586 size_t node_count = ::mdds::dump_tree(m_root_node);
587 size_t node_instance_count = node_base::get_instance_count();
589 cout << "tree node count = " << node_count << " node instance count = " << node_instance_count << endl;
590 assert(node_count == node_instance_count);
593 void dump_leaf_nodes() const
595 using ::std::cout;
596 using ::std::endl;
598 cout << "------------------------------------------" << endl;
600 node_base_ptr cur_node = m_left_leaf;
601 long node_id = 0;
602 while (cur_node)
604 cout << " node " << node_id++ << ": key = " << get_node(cur_node)->value_leaf.key
605 << "; value = " << get_node(cur_node)->value_leaf.value
606 << endl;
607 cur_node = cur_node->right;
609 cout << endl << " node instance count = " << node_base::get_instance_count() << endl;
612 /**
613 * Verify keys in the leaf nodes.
615 * @param key_values vector containing key values in the left-to-right
616 * order, including the key value of the rightmost leaf
617 * node.
619 bool verify_keys(const ::std::vector<key_type>& key_values) const
621 node* cur_node = get_node(m_left_leaf);
622 typename ::std::vector<key_type>::const_iterator itr = key_values.begin(), itr_end = key_values.end();
623 for (; itr != itr_end; ++itr)
625 if (!cur_node)
626 // Position past the right-mode node. Invalid.
627 return false;
629 if (cur_node->value_leaf.key != *itr)
630 // Key values differ.
631 return false;
633 cur_node = get_node(cur_node->right);
636 if (cur_node)
637 // At this point, we expect the current node to be at the position
638 // past the right-most node, which is NULL.
639 return false;
641 return true;
644 /**
645 * Verify values in the leaf nodes.
647 * @param values vector containing values to verify against, in the
648 * left-to-right order, <i>not</i> including the value of
649 * the rightmost leaf node.
651 bool verify_values(const ::std::vector<value_type>& values) const
653 node* cur_node = get_node(m_left_leaf);
654 node* end_node = get_node(m_right_leaf);
655 typename ::std::vector<value_type>::const_iterator itr = values.begin(), itr_end = values.end();
656 for (; itr != itr_end; ++itr)
658 if (cur_node == end_node || !cur_node)
659 return false;
661 if (cur_node->value_leaf.value != *itr)
662 // Key values differ.
663 return false;
665 cur_node = get_node(cur_node->right);
668 if (cur_node != end_node)
669 // At this point, we expect the current node to be at the end of
670 // range.
671 return false;
673 return true;
675 #endif
677 private:
678 flat_segment_tree();
680 node_base_ptr get_insertion_pos_leaf(key_type key, const node_base_ptr& start_pos) const
682 node_base_ptr cur_node = start_pos;
683 while (cur_node)
685 if (key <= get_node(cur_node)->value_leaf.key)
687 // Found the insertion position.
688 return cur_node;
690 cur_node = cur_node->right;
692 return node_base_ptr();
695 const node* get_insertion_pos_leaf(key_type key, const node* start_pos) const
697 const node* cur_node = start_pos;
698 while (cur_node)
700 if (key <= cur_node->value_leaf.key)
702 // Found the insertion position.
703 return cur_node;
705 cur_node = get_node(cur_node->right);
707 return NULL;
710 static void shift_leaf_key_left(node_base_ptr& begin_node, node_base_ptr& end_node, key_type shift_value)
712 node* cur_node_p = get_node(begin_node);
713 node* end_node_p = get_node(end_node);
714 while (cur_node_p != end_node_p)
716 cur_node_p->value_leaf.key -= shift_value;
717 cur_node_p = get_node(cur_node_p->right);
721 static void shift_leaf_key_right(node_base_ptr& cur_node, node_base_ptr& end_node, key_type shift_value)
723 key_type end_node_key = get_node(end_node)->value_leaf.key;
724 while (get_node(cur_node) != get_node(end_node))
726 get_node(cur_node)->value_leaf.key += shift_value;
727 if (get_node(cur_node)->value_leaf.key < end_node_key)
729 // The node is still in-bound. Keep shifting.
730 cur_node = cur_node->right;
731 continue;
734 // This node has been pushed outside the end node position.
735 // Remove all nodes that follows, and connect the previous node
736 // with the end node.
738 node_base_ptr last_node = cur_node->left;
739 while (get_node(cur_node) != get_node(end_node))
741 node_base_ptr next_node = cur_node->right;
742 disconnect_node(cur_node);
743 cur_node = next_node;
745 last_node->right = end_node;
746 end_node->left = last_node;
747 return;
751 private:
752 node_base_ptr m_root_node;
753 node_base_ptr m_left_leaf;
754 node_base_ptr m_right_leaf;
755 value_type m_init_val;
756 bool m_valid_tree;
761 #endif