Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: content/browser/indexed_db/leveldb/avltree.h

Issue 15564008: Migrate the IndexedDB backend from Blink to Chromium (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Accessor naming, use LevelDBSlice ctor explicitly Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Based on Abstract AVL Tree Template v1.5 by Walt Karas
5 * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
33 #define CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
34
35 #include "base/logging.h"
36 #include "content/browser/indexed_db/leveldb/fixed_array.h"
37
38 namespace content {
39
40 // Here is the reference class for BSet.
41 //
42 // class BSet
43 // {
44 // public:
45 //
46 // class ANY_bitref
47 // {
48 // public:
49 // operator bool ();
50 // void operator = (bool b);
51 // };
52 //
53 // // Does not have to initialize bits.
54 // BSet();
55 //
56 // // Must return a valid value for index when 0 <= index < maxDepth
57 // ANY_bitref operator [] (unsigned index);
58 //
59 // // Set all bits to 1.
60 // void set();
61 //
62 // // Set all bits to 0.
63 // void reset();
64 // };
65
66 template <unsigned maxDepth> class AVLTreeDefaultBSet {
67 public:
68 bool& operator[](unsigned i) {
69 #if defined(ADDRESS_SANITIZER)
70 CHECK(i < maxDepth);
71 #endif
72 return m_data[i];
73 }
74 void set() {
75 for (unsigned i = 0; i < maxDepth; ++i)
76 m_data[i] = true;
77 }
78 void reset() {
79 for (unsigned i = 0; i < maxDepth; ++i)
80 m_data[i] = false;
81 }
82
83 private:
84 FixedArray<bool, maxDepth> m_data;
85 };
86
87 // How to determine maxDepth:
88 // d Minimum number of nodes
89 // 2 2
90 // 3 4
91 // 4 7
92 // 5 12
93 // 6 20
94 // 7 33
95 // 8 54
96 // 9 88
97 // 10 143
98 // 11 232
99 // 12 376
100 // 13 609
101 // 14 986
102 // 15 1,596
103 // 16 2,583
104 // 17 4,180
105 // 18 6,764
106 // 19 10,945
107 // 20 17,710
108 // 21 28,656
109 // 22 46,367
110 // 23 75,024
111 // 24 121,392
112 // 25 196,417
113 // 26 317,810
114 // 27 514,228
115 // 28 832,039
116 // 29 1,346,268
117 // 30 2,178,308
118 // 31 3,524,577
119 // 32 5,702,886
120 // 33 9,227,464
121 // 34 14,930,351
122 // 35 24,157,816
123 // 36 39,088,168
124 // 37 63,245,985
125 // 38 102,334,154
126 // 39 165,580,140
127 // 40 267,914,295
128 // 41 433,494,436
129 // 42 701,408,732
130 // 43 1,134,903,169
131 // 44 1,836,311,902
132 // 45 2,971,215,072
133 //
134 // E.g., if, in a particular instantiation, the maximum number of nodes in a
135 // tree instance is 1,000,000, the maximum depth should be 28.
136 // You pick 28 because MN(28) is 832,039, which is less than or equal to
137 // 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000.
138
139 template <class Abstractor,
140 unsigned maxDepth = 32,
141 class BSet = AVLTreeDefaultBSet<maxDepth> >
142 class AVLTree {
143 public:
144
145 typedef typename Abstractor::key key;
146 typedef typename Abstractor::handle handle;
147 typedef typename Abstractor::size size;
148
149 enum SearchType {
150 EQUAL = 1,
151 LESS = 2,
152 GREATER = 4,
153 LESS_EQUAL = EQUAL | LESS,
154 GREATER_EQUAL = EQUAL | GREATER
155 };
156
157 Abstractor& abstractor() { return abs; }
158
159 inline handle insert(handle h);
160
161 inline handle search(key k, SearchType st = EQUAL);
162 inline handle search_least();
163 inline handle search_greatest();
164
165 inline handle remove(key k);
166
167 inline handle subst(handle new_node);
168
169 void purge() { abs.root = null(); }
170
171 bool is_empty() { return abs.root == null(); }
172
173 AVLTree() { abs.root = null(); }
174
175 class Iterator {
176 public:
177
178 // Initialize depth to invalid value, to indicate iterator is
179 // invalid. (Depth is zero-base.)
180 Iterator() { depth = ~0U; }
181
182 void start_iter(AVLTree& tree, key k, SearchType st = EQUAL) {
183 // Mask of high bit in an int.
184 const int MASK_HIGH_BIT = (int) ~((~(unsigned) 0) >> 1);
185
186 // Save the tree that we're going to iterate through in a
187 // member variable.
188 tree_ = &tree;
189
190 int cmp, target_cmp;
191 handle h = tree_->abs.root;
192 unsigned d = 0;
193
194 depth = ~0U;
195
196 if (h == null()) {
197 // Tree is empty.
198 return;
199 }
200
201 if (st & LESS) {
202 // Key can be greater than key of starting node.
203 target_cmp = 1;
204 } else if (st & GREATER) {
205 // Key can be less than key of starting node.
206 target_cmp = -1;
207 } else {
208 // Key must be same as key of starting node.
209 target_cmp = 0;
210 }
211
212 for (;;) {
213 cmp = cmp_k_n(k, h);
214 if (cmp == 0) {
215 if (st & EQUAL) {
216 // Equal node was sought and found as starting node.
217 depth = d;
218 break;
219 }
220 cmp = -target_cmp;
221 } else if (target_cmp != 0) {
222 if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) {
223 // cmp and target_cmp are both negative or both positive.
224 depth = d;
225 }
226 }
227 h = cmp < 0 ? get_lt(h) : get_gt(h);
228 if (h == null())
229 break;
230 branch[d] = cmp > 0;
231 path_h[d++] = h;
232 }
233 }
234
235 void start_iter_least(AVLTree& tree) {
236 tree_ = &tree;
237
238 handle h = tree_->abs.root;
239
240 depth = ~0U;
241
242 branch.reset();
243
244 while (h != null()) {
245 if (depth != ~0U)
246 path_h[depth] = h;
247 depth++;
248 h = get_lt(h);
249 }
250 }
251
252 void start_iter_greatest(AVLTree& tree) {
253 tree_ = &tree;
254
255 handle h = tree_->abs.root;
256
257 depth = ~0U;
258
259 branch.set();
260
261 while (h != null()) {
262 if (depth != ~0U)
263 path_h[depth] = h;
264 depth++;
265 h = get_gt(h);
266 }
267 }
268
269 handle operator*() {
270 if (depth == ~0U)
271 return null();
272
273 return depth == 0 ? tree_->abs.root : path_h[depth - 1];
274 }
275
276 void operator++() {
277 if (depth != ~0U) {
278 handle h = get_gt(**this);
279 if (h == null()) {
280 do {
281 if (depth == 0) {
282 depth = ~0U;
283 break;
284 }
285 depth--;
286 } while (branch[depth]);
287 } else {
288 branch[depth] = true;
289 path_h[depth++] = h;
290 for (;;) {
291 h = get_lt(h);
292 if (h == null())
293 break;
294 branch[depth] = false;
295 path_h[depth++] = h;
296 }
297 }
298 }
299 }
300
301 void operator--() {
302 if (depth != ~0U) {
303 handle h = get_lt(**this);
304 if (h == null()) {
305 do {
306 if (depth == 0) {
307 depth = ~0U;
308 break;
309 }
310 depth--;
311 } while (!branch[depth]);
312 } else {
313 branch[depth] = false;
314 path_h[depth++] = h;
315 for (;;) {
316 h = get_gt(h);
317 if (h == null())
318 break;
319 branch[depth] = true;
320 path_h[depth++] = h;
321 }
322 }
323 }
324 }
325
326 void operator++(int) { ++(*this); }
327 void operator--(int) { --(*this); }
328
329 protected:
330
331 // Tree being iterated over.
332 AVLTree* tree_;
333
334 // Records a path into the tree. If branch[n] is true, indicates
335 // take greater branch from the nth node in the path, otherwise
336 // take the less branch. branch[0] gives branch from root, and
337 // so on.
338 BSet branch;
339
340 // Zero-based depth of path into tree.
341 unsigned depth;
342
343 // Handles of nodes in path from root to current node (returned by *).
344 handle path_h[maxDepth - 1];
345
346 int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); }
347 int cmp_n_n(handle h1, handle h2) {
348 return tree_->abs.compare_node_node(h1, h2);
349 }
350 handle get_lt(handle h) { return tree_->abs.get_less(h); }
351 handle get_gt(handle h) { return tree_->abs.get_greater(h); }
352 handle null() { return tree_->abs.null(); }
353 };
354
355 template <typename fwd_iter> bool build(fwd_iter p, size num_nodes) {
356 if (num_nodes == 0) {
357 abs.root = null();
358 return true;
359 }
360
361 // Gives path to subtree being built. If branch[N] is false, branch
362 // less from the node at depth N, if true branch greater.
363 BSet branch;
364
365 // If rem[N] is true, then for the current subtree at depth N, it's
366 // greater subtree has one more node than it's less subtree.
367 BSet rem;
368
369 // Depth of root node of current subtree.
370 unsigned depth = 0;
371
372 // Number of nodes in current subtree.
373 size num_sub = num_nodes;
374
375 // The algorithm relies on a stack of nodes whose less subtree has
376 // been built, but whose right subtree has not yet been built. The
377 // stack is implemented as linked list. The nodes are linked
378 // together by having the "greater" handle of a node set to the
379 // next node in the list. "less_parent" is the handle of the first
380 // node in the list.
381 handle less_parent = null();
382
383 // h is root of current subtree, child is one of its children.
384 handle h, child;
385
386 for (;;) {
387 while (num_sub > 2) {
388 // Subtract one for root of subtree.
389 num_sub--;
390 rem[depth] = !!(num_sub & 1);
391 branch[depth++] = false;
392 num_sub >>= 1;
393 }
394
395 if (num_sub == 2) {
396 // Build a subtree with two nodes, slanting to greater.
397 // I arbitrarily chose to always have the extra node in the
398 // greater subtree when there is an odd number of nodes to
399 // split between the two subtrees.
400
401 h = *p;
402 p++;
403 child = *p;
404 p++;
405 set_lt(child, null());
406 set_gt(child, null());
407 set_bf(child, 0);
408 set_gt(h, child);
409 set_lt(h, null());
410 set_bf(h, 1);
411 } else { // num_sub == 1
412 // Build a subtree with one node.
413
414 h = *p;
415 p++;
416 set_lt(h, null());
417 set_gt(h, null());
418 set_bf(h, 0);
419 }
420
421 while (depth) {
422 depth--;
423 if (!branch[depth]) {
424 // We've completed a less subtree.
425 break;
426 }
427
428 // We've completed a greater subtree, so attach it to
429 // its parent (that is less than it). We pop the parent
430 // off the stack of less parents.
431 child = h;
432 h = less_parent;
433 less_parent = get_gt(h);
434 set_gt(h, child);
435 // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1
436 num_sub <<= 1;
437 num_sub += 1 - rem[depth];
438 if (num_sub & (num_sub - 1)) {
439 // num_sub is not a power of 2
440 set_bf(h, 0);
441 } else {
442 // num_sub is a power of 2
443 set_bf(h, 1);
444 }
445 }
446
447 if (num_sub == num_nodes) {
448 // We've completed the full tree.
449 break;
450 }
451
452 // The subtree we've completed is the less subtree of the
453 // next node in the sequence.
454
455 child = h;
456 h = *p;
457 p++;
458 set_lt(h, child);
459
460 // Put h into stack of less parents.
461 set_gt(h, less_parent);
462 less_parent = h;
463
464 // Proceed to creating greater than subtree of h.
465 branch[depth] = true;
466 num_sub += rem[depth++];
467
468 } // end for (;;)
469
470 abs.root = h;
471
472 return true;
473 }
474
475 protected:
476
477 friend class Iterator;
478
479 // Create a class whose sole purpose is to take advantage of
480 // the "empty member" optimization.
481 struct abs_plus_root : public Abstractor {
482 // The handle of the root element in the AVL tree.
483 handle root;
484 };
485
486 abs_plus_root abs;
487
488 handle get_lt(handle h) { return abs.get_less(h); }
489 void set_lt(handle h, handle lh) { abs.set_less(h, lh); }
490
491 handle get_gt(handle h) { return abs.get_greater(h); }
492 void set_gt(handle h, handle gh) { abs.set_greater(h, gh); }
493
494 int get_bf(handle h) { return abs.get_balance_factor(h); }
495 void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); }
496
497 int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); }
498 int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); }
499
500 handle null() { return abs.null(); }
501
502 private:
503
504 // Balances subtree, returns handle of root node of subtree
505 // after balancing.
506 handle balance(handle bal_h) {
507 handle deep_h;
508
509 // Either the "greater than" or the "less than" subtree of
510 // this node has to be 2 levels deeper (or else it wouldn't
511 // need balancing).
512
513 if (get_bf(bal_h) > 0) {
514 // "Greater than" subtree is deeper.
515
516 deep_h = get_gt(bal_h);
517
518 if (get_bf(deep_h) < 0) {
519 handle old_h = bal_h;
520 bal_h = get_lt(deep_h);
521
522 set_gt(old_h, get_lt(bal_h));
523 set_lt(deep_h, get_gt(bal_h));
524 set_lt(bal_h, old_h);
525 set_gt(bal_h, deep_h);
526
527 int bf = get_bf(bal_h);
528 if (bf != 0) {
529 if (bf > 0) {
530 set_bf(old_h, -1);
531 set_bf(deep_h, 0);
532 } else {
533 set_bf(deep_h, 1);
534 set_bf(old_h, 0);
535 }
536 set_bf(bal_h, 0);
537 } else {
538 set_bf(old_h, 0);
539 set_bf(deep_h, 0);
540 }
541 } else {
542 set_gt(bal_h, get_lt(deep_h));
543 set_lt(deep_h, bal_h);
544 if (get_bf(deep_h) == 0) {
545 set_bf(deep_h, -1);
546 set_bf(bal_h, 1);
547 } else {
548 set_bf(deep_h, 0);
549 set_bf(bal_h, 0);
550 }
551 bal_h = deep_h;
552 }
553 } else {
554 // "Less than" subtree is deeper.
555
556 deep_h = get_lt(bal_h);
557
558 if (get_bf(deep_h) > 0) {
559 handle old_h = bal_h;
560 bal_h = get_gt(deep_h);
561 set_lt(old_h, get_gt(bal_h));
562 set_gt(deep_h, get_lt(bal_h));
563 set_gt(bal_h, old_h);
564 set_lt(bal_h, deep_h);
565
566 int bf = get_bf(bal_h);
567 if (bf != 0) {
568 if (bf < 0) {
569 set_bf(old_h, 1);
570 set_bf(deep_h, 0);
571 } else {
572 set_bf(deep_h, -1);
573 set_bf(old_h, 0);
574 }
575 set_bf(bal_h, 0);
576 } else {
577 set_bf(old_h, 0);
578 set_bf(deep_h, 0);
579 }
580 } else {
581 set_lt(bal_h, get_gt(deep_h));
582 set_gt(deep_h, bal_h);
583 if (get_bf(deep_h) == 0) {
584 set_bf(deep_h, 1);
585 set_bf(bal_h, -1);
586 } else {
587 set_bf(deep_h, 0);
588 set_bf(bal_h, 0);
589 }
590 bal_h = deep_h;
591 }
592 }
593
594 return bal_h;
595 }
596
597 };
598
599 template <class Abstractor, unsigned maxDepth, class BSet>
600 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
601 AVLTree<Abstractor, maxDepth, BSet>::insert(handle h) {
602 set_lt(h, null());
603 set_gt(h, null());
604 set_bf(h, 0);
605
606 if (abs.root == null()) {
607 abs.root = h;
608 } else {
609 // Last unbalanced node encountered in search for insertion point.
610 handle unbal = null();
611 // Parent of last unbalanced node.
612 handle parent_unbal = null();
613 // Balance factor of last unbalanced node.
614 int unbal_bf;
615
616 // Zero-based depth in tree.
617 unsigned depth = 0, unbal_depth = 0;
618
619 // Records a path into the tree. If branch[n] is true, indicates
620 // take greater branch from the nth node in the path, otherwise
621 // take the less branch. branch[0] gives branch from root, and
622 // so on.
623 BSet branch;
624
625 handle hh = abs.root;
626 handle parent = null();
627 int cmp;
628
629 do {
630 if (get_bf(hh) != 0) {
631 unbal = hh;
632 parent_unbal = parent;
633 unbal_depth = depth;
634 }
635 cmp = cmp_n_n(h, hh);
636 if (cmp == 0) {
637 // Duplicate key.
638 return hh;
639 }
640 parent = hh;
641 hh = cmp < 0 ? get_lt(hh) : get_gt(hh);
642 branch[depth++] = cmp > 0;
643 } while (hh != null());
644
645 // Add node to insert as leaf of tree.
646 if (cmp < 0)
647 set_lt(parent, h);
648 else
649 set_gt(parent, h);
650
651 depth = unbal_depth;
652
653 if (unbal == null()) {
654 hh = abs.root;
655 } else {
656 cmp = branch[depth++] ? 1 : -1;
657 unbal_bf = get_bf(unbal);
658 if (cmp < 0)
659 unbal_bf--;
660 else // cmp > 0
661 unbal_bf++;
662 hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal);
663 if ((unbal_bf != -2) && (unbal_bf != 2)) {
664 // No rebalancing of tree is necessary.
665 set_bf(unbal, unbal_bf);
666 unbal = null();
667 }
668 }
669
670 if (hh != null())
671 while (h != hh) {
672 cmp = branch[depth++] ? 1 : -1;
673 if (cmp < 0) {
674 set_bf(hh, -1);
675 hh = get_lt(hh);
676 } else { // cmp > 0
677 set_bf(hh, 1);
678 hh = get_gt(hh);
679 }
680 }
681
682 if (unbal != null()) {
683 unbal = balance(unbal);
684 if (parent_unbal == null()) {
685 abs.root = unbal;
686 } else {
687 depth = unbal_depth - 1;
688 cmp = branch[depth] ? 1 : -1;
689 if (cmp < 0)
690 set_lt(parent_unbal, unbal);
691 else // cmp > 0
692 set_gt(parent_unbal, unbal);
693 }
694 }
695 }
696
697 return h;
698 }
699
700 template <class Abstractor, unsigned maxDepth, class BSet>
701 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
702 AVLTree<Abstractor, maxDepth, BSet>::search(
703 key k,
704 typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st) {
705 const int MASK_HIGH_BIT = (int) ~((~(unsigned) 0) >> 1);
706
707 int cmp, target_cmp;
708 handle match_h = null();
709 handle h = abs.root;
710
711 if (st & LESS)
712 target_cmp = 1;
713 else if (st & GREATER)
714 target_cmp = -1;
715 else
716 target_cmp = 0;
717
718 while (h != null()) {
719 cmp = cmp_k_n(k, h);
720 if (cmp == 0) {
721 if (st & EQUAL) {
722 match_h = h;
723 break;
724 }
725 cmp = -target_cmp;
726 } else if (target_cmp != 0) {
727 if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) {
728 // cmp and target_cmp are both positive or both negative.
729 match_h = h;
730 }
731 }
732 h = cmp < 0 ? get_lt(h) : get_gt(h);
733 }
734
735 return match_h;
736 }
737
738 template <class Abstractor, unsigned maxDepth, class BSet>
739 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
740 AVLTree<Abstractor, maxDepth, BSet>::search_least() {
741 handle h = abs.root, parent = null();
742
743 while (h != null()) {
744 parent = h;
745 h = get_lt(h);
746 }
747
748 return parent;
749 }
750
751 template <class Abstractor, unsigned maxDepth, class BSet>
752 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
753 AVLTree<Abstractor, maxDepth, BSet>::search_greatest() {
754 handle h = abs.root, parent = null();
755
756 while (h != null()) {
757 parent = h;
758 h = get_gt(h);
759 }
760
761 return parent;
762 }
763
764 template <class Abstractor, unsigned maxDepth, class BSet>
765 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
766 AVLTree<Abstractor, maxDepth, BSet>::remove(key k) {
767 // Zero-based depth in tree.
768 unsigned depth = 0, rm_depth;
769
770 // Records a path into the tree. If branch[n] is true, indicates
771 // take greater branch from the nth node in the path, otherwise
772 // take the less branch. branch[0] gives branch from root, and
773 // so on.
774 BSet branch;
775
776 handle h = abs.root;
777 handle parent = null(), child;
778 int cmp, cmp_shortened_sub_with_path = 0;
779
780 for (;;) {
781 if (h == null()) {
782 // No node in tree with given key.
783 return null();
784 }
785 cmp = cmp_k_n(k, h);
786 if (cmp == 0) {
787 // Found node to remove.
788 break;
789 }
790 parent = h;
791 h = cmp < 0 ? get_lt(h) : get_gt(h);
792 branch[depth++] = cmp > 0;
793 cmp_shortened_sub_with_path = cmp;
794 }
795 handle rm = h;
796 handle parent_rm = parent;
797 rm_depth = depth;
798
799 // If the node to remove is not a leaf node, we need to get a
800 // leaf node, or a node with a single leaf as its child, to put
801 // in the place of the node to remove. We will get the greatest
802 // node in the less subtree (of the node to remove), or the least
803 // node in the greater subtree. We take the leaf node from the
804 // deeper subtree, if there is one.
805
806 if (get_bf(h) < 0) {
807 child = get_lt(h);
808 branch[depth] = false;
809 cmp = -1;
810 } else {
811 child = get_gt(h);
812 branch[depth] = true;
813 cmp = 1;
814 }
815 depth++;
816
817 if (child != null()) {
818 cmp = -cmp;
819 do {
820 parent = h;
821 h = child;
822 if (cmp < 0) {
823 child = get_lt(h);
824 branch[depth] = false;
825 } else {
826 child = get_gt(h);
827 branch[depth] = true;
828 }
829 depth++;
830 } while (child != null());
831
832 if (parent == rm) {
833 // Only went through do loop once. Deleted node will be replaced
834 // in the tree structure by one of its immediate children.
835 cmp_shortened_sub_with_path = -cmp;
836 } else {
837 cmp_shortened_sub_with_path = cmp;
838 }
839
840 // Get the handle of the opposite child, which may not be null.
841 child = cmp > 0 ? get_lt(h) : get_gt(h);
842 }
843
844 if (parent == null()) {
845 // There were only 1 or 2 nodes in this tree.
846 abs.root = child;
847 } else if (cmp_shortened_sub_with_path < 0) {
848 set_lt(parent, child);
849 } else {
850 set_gt(parent, child);
851 }
852
853 // "path" is the parent of the subtree being eliminated or reduced
854 // from a depth of 2 to 1. If "path" is the node to be removed, we
855 // set path to the node we're about to poke into the position of the
856 // node to be removed.
857 handle path = parent == rm ? h : parent;
858
859 if (h != rm) {
860 // Poke in the replacement for the node to be removed.
861 set_lt(h, get_lt(rm));
862 set_gt(h, get_gt(rm));
863 set_bf(h, get_bf(rm));
864 if (parent_rm == null()) {
865 abs.root = h;
866 } else {
867 depth = rm_depth - 1;
868 if (branch[depth])
869 set_gt(parent_rm, h);
870 else
871 set_lt(parent_rm, h);
872 }
873 }
874
875 if (path != null()) {
876 // Create a temporary linked list from the parent of the path node
877 // to the root node.
878 h = abs.root;
879 parent = null();
880 depth = 0;
881 while (h != path) {
882 if (branch[depth++]) {
883 child = get_gt(h);
884 set_gt(h, parent);
885 } else {
886 child = get_lt(h);
887 set_lt(h, parent);
888 }
889 parent = h;
890 h = child;
891 }
892
893 // Climb from the path node to the root node using the linked
894 // list, restoring the tree structure and rebalancing as necessary.
895 bool reduced_depth = true;
896 int bf;
897 cmp = cmp_shortened_sub_with_path;
898 for (;;) {
899 if (reduced_depth) {
900 bf = get_bf(h);
901 if (cmp < 0)
902 bf++;
903 else // cmp > 0
904 bf--;
905 if ((bf == -2) || (bf == 2)) {
906 h = balance(h);
907 bf = get_bf(h);
908 } else {
909 set_bf(h, bf);
910 }
911 reduced_depth = (bf == 0);
912 }
913 if (parent == null())
914 break;
915 child = h;
916 h = parent;
917 cmp = branch[--depth] ? 1 : -1;
918 if (cmp < 0) {
919 parent = get_lt(h);
920 set_lt(h, child);
921 } else {
922 parent = get_gt(h);
923 set_gt(h, child);
924 }
925 }
926 abs.root = h;
927 }
928
929 return rm;
930 }
931
932 template <class Abstractor, unsigned maxDepth, class BSet>
933 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
934 AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node) {
935 handle h = abs.root;
936 handle parent = null();
937 int cmp, last_cmp;
938
939 // Search for node already in tree with same key.
940 for (;;) {
941 if (h == null()) {
942 // No node in tree with same key as new node.
943 return null();
944 }
945 cmp = cmp_n_n(new_node, h);
946 if (cmp == 0) {
947 // Found the node to substitute new one for.
948 break;
949 }
950 last_cmp = cmp;
951 parent = h;
952 h = cmp < 0 ? get_lt(h) : get_gt(h);
953 }
954
955 // Copy tree housekeeping fields from node in tree to new node.
956 set_lt(new_node, get_lt(h));
957 set_gt(new_node, get_gt(h));
958 set_bf(new_node, get_bf(h));
959
960 if (parent == null()) {
961 // New node is also new root.
962 abs.root = new_node;
963 } else {
964 // Make parent point to new node.
965 if (last_cmp < 0)
966 set_lt(parent, new_node);
967 else
968 set_gt(parent, new_node);
969 }
970
971 return h;
972 }
973
974 } // namespace content
975
976 #endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698