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

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: Coding style fixes 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.
dgrogan 2013/05/22 18:22:06 This turned out to be ok?
jamesr 2013/05/22 18:59:44 this doesn't look like the right copyright header.
jsbell 2013/05/22 19:13:04 I asked the lawyerly types what to do here in adva
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 typedef typename Abstractor::key key;
145 typedef typename Abstractor::handle handle;
146 typedef typename Abstractor::size size;
147
148 enum SearchType {
149 EQUAL = 1,
150 LESS = 2,
151 GREATER = 4,
152 LESS_EQUAL = EQUAL | LESS,
153 GREATER_EQUAL = EQUAL | GREATER
154 };
155
156 Abstractor& abstractor() { return abs; }
157
158 inline handle insert(handle h);
159
160 inline handle search(key k, SearchType st = EQUAL);
161 inline handle search_least();
162 inline handle search_greatest();
163
164 inline handle remove(key k);
165
166 inline handle subst(handle new_node);
167
168 void purge() { abs.root = null(); }
169
170 bool is_empty() { return abs.root == null(); }
171
172 AVLTree() { abs.root = null(); }
173
174 class Iterator {
175 public:
176 // Initialize depth to invalid value, to indicate iterator is
177 // invalid. (Depth is zero-base.)
178 Iterator() { depth = ~0U; }
179
180 void start_iter(AVLTree& tree, key k, SearchType st = EQUAL) {
181 // Mask of high bit in an int.
182 const int kMaskHighBit = (int) ~((~(unsigned) 0) >> 1);
183
184 // Save the tree that we're going to iterate through in a
185 // member variable.
186 tree_ = &tree;
187
188 int cmp, target_cmp;
189 handle h = tree_->abs.root;
190 unsigned d = 0;
191
192 depth = ~0U;
193
194 if (h == null()) {
195 // Tree is empty.
196 return;
197 }
198
199 if (st & LESS) {
200 // Key can be greater than key of starting node.
201 target_cmp = 1;
202 } else if (st & GREATER) {
203 // Key can be less than key of starting node.
204 target_cmp = -1;
205 } else {
206 // Key must be same as key of starting node.
207 target_cmp = 0;
208 }
209
210 for (;;) {
211 cmp = cmp_k_n(k, h);
212 if (cmp == 0) {
213 if (st & EQUAL) {
214 // Equal node was sought and found as starting node.
215 depth = d;
216 break;
217 }
218 cmp = -target_cmp;
219 } else if (target_cmp != 0) {
220 if (!((cmp ^ target_cmp) & kMaskHighBit)) {
221 // cmp and target_cmp are both negative or both positive.
222 depth = d;
223 }
224 }
225 h = cmp < 0 ? get_lt(h) : get_gt(h);
226 if (h == null())
227 break;
228 branch[d] = cmp > 0;
229 path_h[d++] = h;
230 }
231 }
232
233 void start_iter_least(AVLTree& tree) {
234 tree_ = &tree;
235
236 handle h = tree_->abs.root;
237
238 depth = ~0U;
239
240 branch.reset();
241
242 while (h != null()) {
243 if (depth != ~0U)
244 path_h[depth] = h;
245 depth++;
246 h = get_lt(h);
247 }
248 }
249
250 void start_iter_greatest(AVLTree& tree) {
251 tree_ = &tree;
252
253 handle h = tree_->abs.root;
254
255 depth = ~0U;
256
257 branch.set();
258
259 while (h != null()) {
260 if (depth != ~0U)
261 path_h[depth] = h;
262 depth++;
263 h = get_gt(h);
264 }
265 }
266
267 handle operator*() {
268 if (depth == ~0U)
269 return null();
270
271 return depth == 0 ? tree_->abs.root : path_h[depth - 1];
272 }
273
274 void operator++() {
275 if (depth != ~0U) {
276 handle h = get_gt(**this);
277 if (h == null()) {
278 do {
279 if (depth == 0) {
280 depth = ~0U;
281 break;
282 }
283 depth--;
284 } while (branch[depth]);
285 } else {
286 branch[depth] = true;
287 path_h[depth++] = h;
288 for (;;) {
289 h = get_lt(h);
290 if (h == null())
291 break;
292 branch[depth] = false;
293 path_h[depth++] = h;
294 }
295 }
296 }
297 }
298
299 void operator--() {
300 if (depth != ~0U) {
301 handle h = get_lt(**this);
302 if (h == null()) {
303 do {
304 if (depth == 0) {
305 depth = ~0U;
306 break;
307 }
308 depth--;
309 } while (!branch[depth]);
310 } else {
311 branch[depth] = false;
312 path_h[depth++] = h;
313 for (;;) {
314 h = get_gt(h);
315 if (h == null())
316 break;
317 branch[depth] = true;
318 path_h[depth++] = h;
319 }
320 }
321 }
322 }
323
324 void operator++(int) { ++(*this); }
325 void operator--(int) { --(*this); }
326
327 protected:
328
329 // Tree being iterated over.
330 AVLTree* tree_;
331
332 // Records a path into the tree. If branch[n] is true, indicates
333 // take greater branch from the nth node in the path, otherwise
334 // take the less branch. branch[0] gives branch from root, and
335 // so on.
336 BSet branch;
337
338 // Zero-based depth of path into tree.
339 unsigned depth;
340
341 // Handles of nodes in path from root to current node (returned by *).
342 handle path_h[maxDepth - 1];
343
344 int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); }
345 int cmp_n_n(handle h1, handle h2) {
346 return tree_->abs.compare_node_node(h1, h2);
347 }
348 handle get_lt(handle h) { return tree_->abs.get_less(h); }
349 handle get_gt(handle h) { return tree_->abs.get_greater(h); }
350 handle null() { return tree_->abs.null(); }
351 };
352
353 template <typename fwd_iter> bool build(fwd_iter p, size num_nodes) {
354 if (num_nodes == 0) {
355 abs.root = null();
356 return true;
357 }
358
359 // Gives path to subtree being built. If branch[N] is false, branch
360 // less from the node at depth N, if true branch greater.
361 BSet branch;
362
363 // If rem[N] is true, then for the current subtree at depth N, it's
364 // greater subtree has one more node than it's less subtree.
365 BSet rem;
366
367 // Depth of root node of current subtree.
368 unsigned depth = 0;
369
370 // Number of nodes in current subtree.
371 size num_sub = num_nodes;
372
373 // The algorithm relies on a stack of nodes whose less subtree has
374 // been built, but whose right subtree has not yet been built. The
375 // stack is implemented as linked list. The nodes are linked
376 // together by having the "greater" handle of a node set to the
377 // next node in the list. "less_parent" is the handle of the first
378 // node in the list.
379 handle less_parent = null();
380
381 // h is root of current subtree, child is one of its children.
382 handle h, child;
383
384 for (;;) {
385 while (num_sub > 2) {
386 // Subtract one for root of subtree.
387 num_sub--;
388 rem[depth] = !!(num_sub & 1);
389 branch[depth++] = false;
390 num_sub >>= 1;
391 }
392
393 if (num_sub == 2) {
394 // Build a subtree with two nodes, slanting to greater.
395 // I arbitrarily chose to always have the extra node in the
396 // greater subtree when there is an odd number of nodes to
397 // split between the two subtrees.
398
399 h = *p;
400 p++;
401 child = *p;
402 p++;
403 set_lt(child, null());
404 set_gt(child, null());
405 set_bf(child, 0);
406 set_gt(h, child);
407 set_lt(h, null());
408 set_bf(h, 1);
409 } else { // num_sub == 1
410 // Build a subtree with one node.
411
412 h = *p;
413 p++;
414 set_lt(h, null());
415 set_gt(h, null());
416 set_bf(h, 0);
417 }
418
419 while (depth) {
420 depth--;
421 if (!branch[depth]) {
422 // We've completed a less subtree.
423 break;
424 }
425
426 // We've completed a greater subtree, so attach it to
427 // its parent (that is less than it). We pop the parent
428 // off the stack of less parents.
429 child = h;
430 h = less_parent;
431 less_parent = get_gt(h);
432 set_gt(h, child);
433 // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1
434 num_sub <<= 1;
435 num_sub += 1 - rem[depth];
436 if (num_sub & (num_sub - 1)) {
437 // num_sub is not a power of 2
438 set_bf(h, 0);
439 } else {
440 // num_sub is a power of 2
441 set_bf(h, 1);
442 }
443 }
444
445 if (num_sub == num_nodes) {
446 // We've completed the full tree.
447 break;
448 }
449
450 // The subtree we've completed is the less subtree of the
451 // next node in the sequence.
452
453 child = h;
454 h = *p;
455 p++;
456 set_lt(h, child);
457
458 // Put h into stack of less parents.
459 set_gt(h, less_parent);
460 less_parent = h;
461
462 // Proceed to creating greater than subtree of h.
463 branch[depth] = true;
464 num_sub += rem[depth++];
465
466 } // end for (;;)
467
468 abs.root = h;
469
470 return true;
471 }
472
473 protected:
474
475 friend class Iterator;
476
477 // Create a class whose sole purpose is to take advantage of
478 // the "empty member" optimization.
479 struct abs_plus_root : public Abstractor {
480 // The handle of the root element in the AVL tree.
481 handle root;
482 };
483
484 abs_plus_root abs;
485
486 handle get_lt(handle h) { return abs.get_less(h); }
487 void set_lt(handle h, handle lh) { abs.set_less(h, lh); }
488
489 handle get_gt(handle h) { return abs.get_greater(h); }
490 void set_gt(handle h, handle gh) { abs.set_greater(h, gh); }
491
492 int get_bf(handle h) { return abs.get_balance_factor(h); }
493 void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); }
494
495 int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); }
496 int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); }
497
498 handle null() { return abs.null(); }
499
500 private:
501
502 // Balances subtree, returns handle of root node of subtree
503 // after balancing.
504 handle balance(handle bal_h) {
505 handle deep_h;
506
507 // Either the "greater than" or the "less than" subtree of
508 // this node has to be 2 levels deeper (or else it wouldn't
509 // need balancing).
510
511 if (get_bf(bal_h) > 0) {
512 // "Greater than" subtree is deeper.
513
514 deep_h = get_gt(bal_h);
515
516 if (get_bf(deep_h) < 0) {
517 handle old_h = bal_h;
518 bal_h = get_lt(deep_h);
519
520 set_gt(old_h, get_lt(bal_h));
521 set_lt(deep_h, get_gt(bal_h));
522 set_lt(bal_h, old_h);
523 set_gt(bal_h, deep_h);
524
525 int bf = get_bf(bal_h);
526 if (bf != 0) {
527 if (bf > 0) {
528 set_bf(old_h, -1);
529 set_bf(deep_h, 0);
530 } else {
531 set_bf(deep_h, 1);
532 set_bf(old_h, 0);
533 }
534 set_bf(bal_h, 0);
535 } else {
536 set_bf(old_h, 0);
537 set_bf(deep_h, 0);
538 }
539 } else {
540 set_gt(bal_h, get_lt(deep_h));
541 set_lt(deep_h, bal_h);
542 if (get_bf(deep_h) == 0) {
543 set_bf(deep_h, -1);
544 set_bf(bal_h, 1);
545 } else {
546 set_bf(deep_h, 0);
547 set_bf(bal_h, 0);
548 }
549 bal_h = deep_h;
550 }
551 } else {
552 // "Less than" subtree is deeper.
553
554 deep_h = get_lt(bal_h);
555
556 if (get_bf(deep_h) > 0) {
557 handle old_h = bal_h;
558 bal_h = get_gt(deep_h);
559 set_lt(old_h, get_gt(bal_h));
560 set_gt(deep_h, get_lt(bal_h));
561 set_gt(bal_h, old_h);
562 set_lt(bal_h, deep_h);
563
564 int bf = get_bf(bal_h);
565 if (bf != 0) {
566 if (bf < 0) {
567 set_bf(old_h, 1);
568 set_bf(deep_h, 0);
569 } else {
570 set_bf(deep_h, -1);
571 set_bf(old_h, 0);
572 }
573 set_bf(bal_h, 0);
574 } else {
575 set_bf(old_h, 0);
576 set_bf(deep_h, 0);
577 }
578 } else {
579 set_lt(bal_h, get_gt(deep_h));
580 set_gt(deep_h, bal_h);
581 if (get_bf(deep_h) == 0) {
582 set_bf(deep_h, 1);
583 set_bf(bal_h, -1);
584 } else {
585 set_bf(deep_h, 0);
586 set_bf(bal_h, 0);
587 }
588 bal_h = deep_h;
589 }
590 }
591
592 return bal_h;
593 }
594
595 };
596
597 template <class Abstractor, unsigned maxDepth, class BSet>
598 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
599 AVLTree<Abstractor, maxDepth, BSet>::insert(handle h) {
600 set_lt(h, null());
601 set_gt(h, null());
602 set_bf(h, 0);
603
604 if (abs.root == null()) {
605 abs.root = h;
606 } else {
607 // Last unbalanced node encountered in search for insertion point.
608 handle unbal = null();
609 // Parent of last unbalanced node.
610 handle parent_unbal = null();
611 // Balance factor of last unbalanced node.
612 int unbal_bf;
613
614 // Zero-based depth in tree.
615 unsigned depth = 0, unbal_depth = 0;
616
617 // Records a path into the tree. If branch[n] is true, indicates
618 // take greater branch from the nth node in the path, otherwise
619 // take the less branch. branch[0] gives branch from root, and
620 // so on.
621 BSet branch;
622
623 handle hh = abs.root;
624 handle parent = null();
625 int cmp;
626
627 do {
628 if (get_bf(hh) != 0) {
629 unbal = hh;
630 parent_unbal = parent;
631 unbal_depth = depth;
632 }
633 cmp = cmp_n_n(h, hh);
634 if (cmp == 0) {
635 // Duplicate key.
636 return hh;
637 }
638 parent = hh;
639 hh = cmp < 0 ? get_lt(hh) : get_gt(hh);
640 branch[depth++] = cmp > 0;
641 } while (hh != null());
642
643 // Add node to insert as leaf of tree.
644 if (cmp < 0)
645 set_lt(parent, h);
646 else
647 set_gt(parent, h);
648
649 depth = unbal_depth;
650
651 if (unbal == null()) {
652 hh = abs.root;
653 } else {
654 cmp = branch[depth++] ? 1 : -1;
655 unbal_bf = get_bf(unbal);
656 if (cmp < 0)
657 unbal_bf--;
658 else // cmp > 0
659 unbal_bf++;
660 hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal);
661 if ((unbal_bf != -2) && (unbal_bf != 2)) {
662 // No rebalancing of tree is necessary.
663 set_bf(unbal, unbal_bf);
664 unbal = null();
665 }
666 }
667
668 if (hh != null()) {
669 while (h != hh) {
670 cmp = branch[depth++] ? 1 : -1;
671 if (cmp < 0) {
672 set_bf(hh, -1);
673 hh = get_lt(hh);
674 } else { // cmp > 0
675 set_bf(hh, 1);
676 hh = get_gt(hh);
677 }
678 }
679 }
680
681 if (unbal != null()) {
682 unbal = balance(unbal);
683 if (parent_unbal == null()) {
684 abs.root = unbal;
685 } else {
686 depth = unbal_depth - 1;
687 cmp = branch[depth] ? 1 : -1;
688 if (cmp < 0)
689 set_lt(parent_unbal, unbal);
690 else // cmp > 0
691 set_gt(parent_unbal, unbal);
692 }
693 }
694 }
695
696 return h;
697 }
698
699 template <class Abstractor, unsigned maxDepth, class BSet>
700 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
701 AVLTree<Abstractor, maxDepth, BSet>::search(
702 key k,
703 typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st) {
704 const int kMaskHighBit = (int) ~((~(unsigned) 0) >> 1);
705
706 int cmp, target_cmp;
707 handle match_h = null();
708 handle h = abs.root;
709
710 if (st & LESS)
711 target_cmp = 1;
712 else if (st & GREATER)
713 target_cmp = -1;
714 else
715 target_cmp = 0;
716
717 while (h != null()) {
718 cmp = cmp_k_n(k, h);
719 if (cmp == 0) {
720 if (st & EQUAL) {
721 match_h = h;
722 break;
723 }
724 cmp = -target_cmp;
725 } else if (target_cmp != 0) {
726 if (!((cmp ^ target_cmp) & kMaskHighBit)) {
727 // cmp and target_cmp are both positive or both negative.
728 match_h = h;
729 }
730 }
731 h = cmp < 0 ? get_lt(h) : get_gt(h);
732 }
733
734 return match_h;
735 }
736
737 template <class Abstractor, unsigned maxDepth, class BSet>
738 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
739 AVLTree<Abstractor, maxDepth, BSet>::search_least() {
740 handle h = abs.root, parent = null();
741
742 while (h != null()) {
743 parent = h;
744 h = get_lt(h);
745 }
746
747 return parent;
748 }
749
750 template <class Abstractor, unsigned maxDepth, class BSet>
751 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
752 AVLTree<Abstractor, maxDepth, BSet>::search_greatest() {
753 handle h = abs.root, parent = null();
754
755 while (h != null()) {
756 parent = h;
757 h = get_gt(h);
758 }
759
760 return parent;
761 }
762
763 template <class Abstractor, unsigned maxDepth, class BSet>
764 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
765 AVLTree<Abstractor, maxDepth, BSet>::remove(key k) {
766 // Zero-based depth in tree.
767 unsigned depth = 0, rm_depth;
768
769 // Records a path into the tree. If branch[n] is true, indicates
770 // take greater branch from the nth node in the path, otherwise
771 // take the less branch. branch[0] gives branch from root, and
772 // so on.
773 BSet branch;
774
775 handle h = abs.root;
776 handle parent = null(), child;
777 int cmp, cmp_shortened_sub_with_path = 0;
778
779 for (;;) {
780 if (h == null()) {
781 // No node in tree with given key.
782 return null();
783 }
784 cmp = cmp_k_n(k, h);
785 if (cmp == 0) {
786 // Found node to remove.
787 break;
788 }
789 parent = h;
790 h = cmp < 0 ? get_lt(h) : get_gt(h);
791 branch[depth++] = cmp > 0;
792 cmp_shortened_sub_with_path = cmp;
793 }
794 handle rm = h;
795 handle parent_rm = parent;
796 rm_depth = depth;
797
798 // If the node to remove is not a leaf node, we need to get a
799 // leaf node, or a node with a single leaf as its child, to put
800 // in the place of the node to remove. We will get the greatest
801 // node in the less subtree (of the node to remove), or the least
802 // node in the greater subtree. We take the leaf node from the
803 // deeper subtree, if there is one.
804
805 if (get_bf(h) < 0) {
806 child = get_lt(h);
807 branch[depth] = false;
808 cmp = -1;
809 } else {
810 child = get_gt(h);
811 branch[depth] = true;
812 cmp = 1;
813 }
814 depth++;
815
816 if (child != null()) {
817 cmp = -cmp;
818 do {
819 parent = h;
820 h = child;
821 if (cmp < 0) {
822 child = get_lt(h);
823 branch[depth] = false;
824 } else {
825 child = get_gt(h);
826 branch[depth] = true;
827 }
828 depth++;
829 } while (child != null());
830
831 if (parent == rm) {
832 // Only went through do loop once. Deleted node will be replaced
833 // in the tree structure by one of its immediate children.
834 cmp_shortened_sub_with_path = -cmp;
835 } else {
836 cmp_shortened_sub_with_path = cmp;
837 }
838
839 // Get the handle of the opposite child, which may not be null.
840 child = cmp > 0 ? get_lt(h) : get_gt(h);
841 }
842
843 if (parent == null()) {
844 // There were only 1 or 2 nodes in this tree.
845 abs.root = child;
846 } else if (cmp_shortened_sub_with_path < 0) {
847 set_lt(parent, child);
848 } else {
849 set_gt(parent, child);
850 }
851
852 // "path" is the parent of the subtree being eliminated or reduced
853 // from a depth of 2 to 1. If "path" is the node to be removed, we
854 // set path to the node we're about to poke into the position of the
855 // node to be removed.
856 handle path = parent == rm ? h : parent;
857
858 if (h != rm) {
859 // Poke in the replacement for the node to be removed.
860 set_lt(h, get_lt(rm));
861 set_gt(h, get_gt(rm));
862 set_bf(h, get_bf(rm));
863 if (parent_rm == null()) {
864 abs.root = h;
865 } else {
866 depth = rm_depth - 1;
867 if (branch[depth])
868 set_gt(parent_rm, h);
869 else
870 set_lt(parent_rm, h);
871 }
872 }
873
874 if (path != null()) {
875 // Create a temporary linked list from the parent of the path node
876 // to the root node.
877 h = abs.root;
878 parent = null();
879 depth = 0;
880 while (h != path) {
881 if (branch[depth++]) {
882 child = get_gt(h);
883 set_gt(h, parent);
884 } else {
885 child = get_lt(h);
886 set_lt(h, parent);
887 }
888 parent = h;
889 h = child;
890 }
891
892 // Climb from the path node to the root node using the linked
893 // list, restoring the tree structure and rebalancing as necessary.
894 bool reduced_depth = true;
895 int bf;
896 cmp = cmp_shortened_sub_with_path;
897 for (;;) {
898 if (reduced_depth) {
899 bf = get_bf(h);
900 if (cmp < 0)
901 bf++;
902 else // cmp > 0
903 bf--;
904 if ((bf == -2) || (bf == 2)) {
905 h = balance(h);
906 bf = get_bf(h);
907 } else {
908 set_bf(h, bf);
909 }
910 reduced_depth = (bf == 0);
911 }
912 if (parent == null())
913 break;
914 child = h;
915 h = parent;
916 cmp = branch[--depth] ? 1 : -1;
917 if (cmp < 0) {
918 parent = get_lt(h);
919 set_lt(h, child);
920 } else {
921 parent = get_gt(h);
922 set_gt(h, child);
923 }
924 }
925 abs.root = h;
926 }
927
928 return rm;
929 }
930
931 template <class Abstractor, unsigned maxDepth, class BSet>
932 inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
933 AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node) {
934 handle h = abs.root;
935 handle parent = null();
936 int cmp, last_cmp;
937
938 // Search for node already in tree with same key.
939 for (;;) {
940 if (h == null()) {
941 // No node in tree with same key as new node.
942 return null();
943 }
944 cmp = cmp_n_n(new_node, h);
945 if (cmp == 0) {
946 // Found the node to substitute new one for.
947 break;
948 }
949 last_cmp = cmp;
950 parent = h;
951 h = cmp < 0 ? get_lt(h) : get_gt(h);
952 }
953
954 // Copy tree housekeeping fields from node in tree to new node.
955 set_lt(new_node, get_lt(h));
956 set_gt(new_node, get_gt(h));
957 set_bf(new_node, get_bf(h));
958
959 if (parent == null()) {
960 // New node is also new root.
961 abs.root = new_node;
962 } else {
963 // Make parent point to new node.
964 if (last_cmp < 0)
965 set_lt(parent, new_node);
966 else
967 set_gt(parent, new_node);
968 }
969
970 return h;
971 }
972
973 } // namespace content
974
975 #endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_AVLTREE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698