1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // Portions of this file were originally under the following license:
9 // Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
10 // All rights reserved.
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions
15 // 1. Redistributions of source code must retain the above copyright
16 // notice(s), this list of conditions and the following disclaimer
17 // unmodified other than the allowable addition of one or more
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice(s), this list of conditions and the following disclaimer in
21 // the documentation and/or other materials provided with the
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
25 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
28 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
34 // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // ****************************************************************************
38 // C++ template implementation of left-leaning red-black trees.
40 // All operations are done non-recursively. Parent pointers are not used, and
41 // color bits are stored in the least significant bit of right-child pointers,
42 // thus making node linkage as compact as is possible for red-black trees.
44 // The RedBlackTree template expects two type arguments: the type of the nodes,
45 // containing a RedBlackTreeNode, and a trait providing two methods:
46 // - a GetTreeNode method that returns a reference to the RedBlackTreeNode
47 // corresponding to a given node with the following signature:
48 // static RedBlackTreeNode<T>& GetTreeNode(T*)
49 // - a Compare function with the following signature:
50 // static Order Compare(T* aNode, T* aOther)
54 // Interpretation of comparision function return values:
56 // Order::eLess: aNode < aOther
57 // Order::eEqual: aNode == aOther
58 // Order::eGreater: aNode > aOther
60 // In all cases, the aNode or aKey argument is the first argument to the
61 // comparison function, which makes it possible to write comparison functions
62 // that treat the first argument specially.
64 // ***************************************************************************
69 #include "mozilla/Alignment.h"
70 #include "mozilla/Assertions.h"
80 class RedBlackTreeNode
{
82 // The lowest bit is the color
86 T
* Left() { return mLeft
; }
88 void SetLeft(T
* aValue
) { mLeft
= aValue
; }
91 return reinterpret_cast<T
*>(reinterpret_cast<uintptr_t>(mRightAndColor
) &
95 void SetRight(T
* aValue
) {
96 mRightAndColor
= reinterpret_cast<T
*>(
97 (reinterpret_cast<uintptr_t>(aValue
) & uintptr_t(~1)) | Color());
101 return static_cast<NodeColor
>(reinterpret_cast<uintptr_t>(mRightAndColor
) &
105 bool IsBlack() { return Color() == NodeColor::Black
; }
107 bool IsRed() { return Color() == NodeColor::Red
; }
109 void SetColor(NodeColor aColor
) {
110 mRightAndColor
= reinterpret_cast<T
*>(
111 (reinterpret_cast<uintptr_t>(mRightAndColor
) & uintptr_t(~1)) | aColor
);
116 template <typename T
, typename Trait
>
119 void Init() { mRoot
= nullptr; }
121 T
* First(T
* aStart
= nullptr) { return First(TreeNode(aStart
)).Get(); }
123 T
* Last(T
* aStart
= nullptr) { return Last(TreeNode(aStart
)).Get(); }
125 T
* Next(T
* aNode
) { return Next(TreeNode(aNode
)).Get(); }
127 T
* Prev(T
* aNode
) { return Prev(TreeNode(aNode
)).Get(); }
129 T
* Search(T
* aKey
) { return Search(TreeNode(aKey
)).Get(); }
131 // Find a match if it exists. Otherwise, find the next greater node, if one
133 T
* SearchOrNext(T
* aKey
) { return SearchOrNext(TreeNode(aKey
)).Get(); }
135 void Insert(T
* aNode
) { Insert(TreeNode(aNode
)); }
137 void Remove(T
* aNode
) { Remove(TreeNode(aNode
)); }
139 // Helper class to avoid having all the tree traversal code further below
140 // have to use Trait::GetTreeNode and do manual null pointer checks, adding
141 // visual noise. Practically speaking TreeNode(nullptr) acts as a virtual
142 // sentinel, that loops back to itself for Left() and Right() and is always
146 constexpr TreeNode() : mNode(nullptr) {}
148 MOZ_IMPLICIT
TreeNode(T
* aNode
) : mNode(aNode
) {}
150 TreeNode
& operator=(TreeNode aOther
) {
151 mNode
= aOther
.mNode
;
156 return TreeNode(mNode
? Trait::GetTreeNode(mNode
).Left() : nullptr);
159 void SetLeft(TreeNode aNode
) {
160 MOZ_RELEASE_ASSERT(mNode
);
161 Trait::GetTreeNode(mNode
).SetLeft(aNode
.mNode
);
165 return TreeNode(mNode
? Trait::GetTreeNode(mNode
).Right() : nullptr);
168 void SetRight(TreeNode aNode
) {
169 MOZ_RELEASE_ASSERT(mNode
);
170 Trait::GetTreeNode(mNode
).SetRight(aNode
.mNode
);
174 return mNode
? Trait::GetTreeNode(mNode
).Color() : NodeColor::Black
;
177 bool IsRed() { return Color() == NodeColor::Red
; }
179 bool IsBlack() { return Color() == NodeColor::Black
; }
181 void SetColor(NodeColor aColor
) {
182 MOZ_RELEASE_ASSERT(mNode
);
183 Trait::GetTreeNode(mNode
).SetColor(aColor
);
186 T
* Get() { return mNode
; }
188 MOZ_IMPLICIT
operator bool() { return !!mNode
; }
190 bool operator==(TreeNode
& aOther
) { return mNode
== aOther
.mNode
; }
197 // Ideally we'd use a TreeNode for mRoot, but we need RedBlackTree to stay
198 // a POD type to avoid a static initializer for gArenas.
201 TreeNode
First(TreeNode aStart
) {
203 for (ret
= aStart
? aStart
: mRoot
; ret
.Left(); ret
= ret
.Left()) {
208 TreeNode
Last(TreeNode aStart
) {
210 for (ret
= aStart
? aStart
: mRoot
; ret
.Right(); ret
= ret
.Right()) {
215 TreeNode
Next(TreeNode aNode
) {
218 ret
= First(aNode
.Right());
220 TreeNode rbp_n_t
= mRoot
;
224 Order rbp_n_cmp
= Trait::Compare(aNode
.Get(), rbp_n_t
.Get());
225 if (rbp_n_cmp
== Order::eLess
) {
227 rbp_n_t
= rbp_n_t
.Left();
228 } else if (rbp_n_cmp
== Order::eGreater
) {
229 rbp_n_t
= rbp_n_t
.Right();
239 TreeNode
Prev(TreeNode aNode
) {
242 ret
= Last(aNode
.Left());
244 TreeNode rbp_p_t
= mRoot
;
248 Order rbp_p_cmp
= Trait::Compare(aNode
.Get(), rbp_p_t
.Get());
249 if (rbp_p_cmp
== Order::eLess
) {
250 rbp_p_t
= rbp_p_t
.Left();
251 } else if (rbp_p_cmp
== Order::eGreater
) {
253 rbp_p_t
= rbp_p_t
.Right();
263 TreeNode
Search(TreeNode aKey
) {
264 TreeNode ret
= mRoot
;
266 while (ret
&& (rbp_se_cmp
= Trait::Compare(aKey
.Get(), ret
.Get())) !=
268 if (rbp_se_cmp
== Order::eLess
) {
277 TreeNode
SearchOrNext(TreeNode aKey
) {
278 TreeNode ret
= nullptr;
279 TreeNode rbp_ns_t
= mRoot
;
281 Order rbp_ns_cmp
= Trait::Compare(aKey
.Get(), rbp_ns_t
.Get());
282 if (rbp_ns_cmp
== Order::eLess
) {
284 rbp_ns_t
= rbp_ns_t
.Left();
285 } else if (rbp_ns_cmp
== Order::eGreater
) {
286 rbp_ns_t
= rbp_ns_t
.Right();
295 void Insert(TreeNode aNode
) {
296 // rbp_i_s is only used as a placeholder for its RedBlackTreeNode. Use
297 // AlignedStorage2 to avoid running the TreeNode base class constructor.
298 mozilla::AlignedStorage2
<T
> rbp_i_s
;
299 TreeNode rbp_i_g
, rbp_i_p
, rbp_i_c
, rbp_i_t
, rbp_i_u
;
300 Order rbp_i_cmp
= Order::eEqual
;
302 rbp_i_p
= rbp_i_s
.addr();
303 rbp_i_p
.SetLeft(mRoot
);
304 rbp_i_p
.SetRight(nullptr);
305 rbp_i_p
.SetColor(NodeColor::Black
);
307 // Iteratively search down the tree for the insertion point,
308 // splitting 4-nodes as they are encountered. At the end of each
309 // iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down
310 // the tree, assuming a sufficiently deep tree.
312 rbp_i_t
= rbp_i_c
.Left();
313 rbp_i_u
= rbp_i_t
.Left();
314 if (rbp_i_t
.IsRed() && rbp_i_u
.IsRed()) {
315 // rbp_i_c is the top of a logical 4-node, so split it.
316 // This iteration does not move down the tree, due to the
317 // disruptiveness of node splitting.
320 rbp_i_t
= RotateRight(rbp_i_c
);
321 // Pass red links up one level.
322 rbp_i_u
= rbp_i_t
.Left();
323 rbp_i_u
.SetColor(NodeColor::Black
);
324 if (rbp_i_p
.Left() == rbp_i_c
) {
325 rbp_i_p
.SetLeft(rbp_i_t
);
328 // rbp_i_c was the right child of rbp_i_p, so rotate
329 // left in order to maintain the left-leaning invariant.
330 MOZ_ASSERT(rbp_i_p
.Right() == rbp_i_c
);
331 rbp_i_p
.SetRight(rbp_i_t
);
332 rbp_i_u
= LeanLeft(rbp_i_p
);
333 if (rbp_i_g
.Left() == rbp_i_p
) {
334 rbp_i_g
.SetLeft(rbp_i_u
);
336 MOZ_ASSERT(rbp_i_g
.Right() == rbp_i_p
);
337 rbp_i_g
.SetRight(rbp_i_u
);
340 rbp_i_cmp
= Trait::Compare(aNode
.Get(), rbp_i_p
.Get());
341 if (rbp_i_cmp
== Order::eLess
) {
342 rbp_i_c
= rbp_i_p
.Left();
344 MOZ_ASSERT(rbp_i_cmp
== Order::eGreater
);
345 rbp_i_c
= rbp_i_p
.Right();
352 rbp_i_cmp
= Trait::Compare(aNode
.Get(), rbp_i_c
.Get());
353 if (rbp_i_cmp
== Order::eLess
) {
354 rbp_i_c
= rbp_i_c
.Left();
356 MOZ_ASSERT(rbp_i_cmp
== Order::eGreater
);
357 rbp_i_c
= rbp_i_c
.Right();
360 // rbp_i_p now refers to the node under which to insert.
361 aNode
.SetLeft(nullptr);
362 aNode
.SetRight(nullptr);
363 aNode
.SetColor(NodeColor::Red
);
364 if (rbp_i_cmp
== Order::eGreater
) {
365 rbp_i_p
.SetRight(aNode
);
366 rbp_i_t
= LeanLeft(rbp_i_p
);
367 if (rbp_i_g
.Left() == rbp_i_p
) {
368 rbp_i_g
.SetLeft(rbp_i_t
);
369 } else if (rbp_i_g
.Right() == rbp_i_p
) {
370 rbp_i_g
.SetRight(rbp_i_t
);
373 rbp_i_p
.SetLeft(aNode
);
375 // Update the root and make sure that it is black.
376 TreeNode root
= TreeNode(rbp_i_s
.addr()).Left();
377 root
.SetColor(NodeColor::Black
);
381 void Remove(TreeNode aNode
) {
382 // rbp_r_s is only used as a placeholder for its RedBlackTreeNode. Use
383 // AlignedStorage2 to avoid running the TreeNode base class constructor.
384 mozilla::AlignedStorage2
<T
> rbp_r_s
;
385 TreeNode rbp_r_p
, rbp_r_c
, rbp_r_xp
, rbp_r_t
, rbp_r_u
;
387 rbp_r_p
= TreeNode(rbp_r_s
.addr());
388 rbp_r_p
.SetLeft(mRoot
);
389 rbp_r_p
.SetRight(nullptr);
390 rbp_r_p
.SetColor(NodeColor::Black
);
393 // Iterate down the tree, but always transform 2-nodes to 3- or
394 // 4-nodes in order to maintain the invariant that the current
395 // node is not a 2-node. This allows simple deletion once a leaf
396 // is reached. Handle the root specially though, since there may
397 // be no way to convert it from a 2-node to a 3-node.
398 rbp_r_cmp
= Trait::Compare(aNode
.Get(), rbp_r_c
.Get());
399 if (rbp_r_cmp
== Order::eLess
) {
400 rbp_r_t
= rbp_r_c
.Left();
401 rbp_r_u
= rbp_r_t
.Left();
402 if (rbp_r_t
.IsBlack() && rbp_r_u
.IsBlack()) {
403 // Apply standard transform to prepare for left move.
404 rbp_r_t
= MoveRedLeft(rbp_r_c
);
405 rbp_r_t
.SetColor(NodeColor::Black
);
406 rbp_r_p
.SetLeft(rbp_r_t
);
411 rbp_r_c
= rbp_r_c
.Left();
414 if (rbp_r_cmp
== Order::eEqual
) {
415 MOZ_ASSERT(aNode
== rbp_r_c
);
416 if (!rbp_r_c
.Right()) {
417 // Delete root node (which is also a leaf node).
418 if (rbp_r_c
.Left()) {
419 rbp_r_t
= LeanRight(rbp_r_c
);
420 rbp_r_t
.SetRight(nullptr);
424 rbp_r_p
.SetLeft(rbp_r_t
);
426 // This is the node we want to delete, but we will
427 // instead swap it with its successor and delete the
428 // successor. Record enough information to do the
429 // swap later. rbp_r_xp is the aNode's parent.
431 rbp_r_cmp
= Order::eGreater
; // Note that deletion is incomplete.
434 if (rbp_r_cmp
== Order::eGreater
) {
435 if (rbp_r_c
.Right().Left().IsBlack()) {
436 rbp_r_t
= rbp_r_c
.Left();
437 if (rbp_r_t
.IsRed()) {
438 // Standard transform.
439 rbp_r_t
= MoveRedRight(rbp_r_c
);
441 // Root-specific transform.
442 rbp_r_c
.SetColor(NodeColor::Red
);
443 rbp_r_u
= rbp_r_t
.Left();
444 if (rbp_r_u
.IsRed()) {
445 rbp_r_u
.SetColor(NodeColor::Black
);
446 rbp_r_t
= RotateRight(rbp_r_c
);
447 rbp_r_u
= RotateLeft(rbp_r_c
);
448 rbp_r_t
.SetRight(rbp_r_u
);
450 rbp_r_t
.SetColor(NodeColor::Red
);
451 rbp_r_t
= RotateLeft(rbp_r_c
);
454 rbp_r_p
.SetLeft(rbp_r_t
);
459 rbp_r_c
= rbp_r_c
.Right();
463 if (rbp_r_cmp
!= Order::eEqual
) {
466 rbp_r_cmp
= Trait::Compare(aNode
.Get(), rbp_r_c
.Get());
467 if (rbp_r_cmp
== Order::eLess
) {
468 rbp_r_t
= rbp_r_c
.Left();
470 // rbp_r_c now refers to the successor node to
471 // relocate, and rbp_r_xp/aNode refer to the
472 // context for the relocation.
473 if (rbp_r_xp
.Left() == aNode
) {
474 rbp_r_xp
.SetLeft(rbp_r_c
);
476 MOZ_ASSERT(rbp_r_xp
.Right() == (aNode
));
477 rbp_r_xp
.SetRight(rbp_r_c
);
479 rbp_r_c
.SetLeft(aNode
.Left());
480 rbp_r_c
.SetRight(aNode
.Right());
481 rbp_r_c
.SetColor(aNode
.Color());
482 if (rbp_r_p
.Left() == rbp_r_c
) {
483 rbp_r_p
.SetLeft(nullptr);
485 MOZ_ASSERT(rbp_r_p
.Right() == rbp_r_c
);
486 rbp_r_p
.SetRight(nullptr);
490 rbp_r_u
= rbp_r_t
.Left();
491 if (rbp_r_t
.IsBlack() && rbp_r_u
.IsBlack()) {
492 rbp_r_t
= MoveRedLeft(rbp_r_c
);
493 if (rbp_r_p
.Left() == rbp_r_c
) {
494 rbp_r_p
.SetLeft(rbp_r_t
);
496 rbp_r_p
.SetRight(rbp_r_t
);
501 rbp_r_c
= rbp_r_c
.Left();
504 // Check whether to delete this node (it has to be
505 // the correct node and a leaf node).
506 if (rbp_r_cmp
== Order::eEqual
) {
507 MOZ_ASSERT(aNode
== rbp_r_c
);
508 if (!rbp_r_c
.Right()) {
510 if (rbp_r_c
.Left()) {
511 rbp_r_t
= LeanRight(rbp_r_c
);
512 rbp_r_t
.SetRight(nullptr);
516 if (rbp_r_p
.Left() == rbp_r_c
) {
517 rbp_r_p
.SetLeft(rbp_r_t
);
519 rbp_r_p
.SetRight(rbp_r_t
);
523 // This is the node we want to delete, but we
524 // will instead swap it with its successor
525 // and delete the successor. Record enough
526 // information to do the swap later.
527 // rbp_r_xp is aNode's parent.
530 rbp_r_t
= rbp_r_c
.Right();
531 rbp_r_u
= rbp_r_t
.Left();
532 if (rbp_r_u
.IsBlack()) {
533 rbp_r_t
= MoveRedRight(rbp_r_c
);
534 if (rbp_r_p
.Left() == rbp_r_c
) {
535 rbp_r_p
.SetLeft(rbp_r_t
);
537 rbp_r_p
.SetRight(rbp_r_t
);
542 rbp_r_c
= rbp_r_c
.Right();
548 mRoot
= TreeNode(rbp_r_s
.addr()).Left().Get();
549 aNode
.SetLeft(nullptr);
550 aNode
.SetRight(nullptr);
551 aNode
.SetColor(NodeColor::Black
);
554 TreeNode
RotateLeft(TreeNode aNode
) {
555 TreeNode node
= aNode
.Right();
556 aNode
.SetRight(node
.Left());
561 TreeNode
RotateRight(TreeNode aNode
) {
562 TreeNode node
= aNode
.Left();
563 aNode
.SetLeft(node
.Right());
564 node
.SetRight(aNode
);
568 TreeNode
LeanLeft(TreeNode aNode
) {
569 TreeNode node
= RotateLeft(aNode
);
570 NodeColor color
= aNode
.Color();
571 node
.SetColor(color
);
572 aNode
.SetColor(NodeColor::Red
);
576 TreeNode
LeanRight(TreeNode aNode
) {
577 TreeNode node
= RotateRight(aNode
);
578 NodeColor color
= aNode
.Color();
579 node
.SetColor(color
);
580 aNode
.SetColor(NodeColor::Red
);
584 TreeNode
MoveRedLeft(TreeNode aNode
) {
586 TreeNode rbp_mrl_t
, rbp_mrl_u
;
587 rbp_mrl_t
= aNode
.Left();
588 rbp_mrl_t
.SetColor(NodeColor::Red
);
589 rbp_mrl_t
= aNode
.Right();
590 rbp_mrl_u
= rbp_mrl_t
.Left();
591 if (rbp_mrl_u
.IsRed()) {
592 rbp_mrl_u
= RotateRight(rbp_mrl_t
);
593 aNode
.SetRight(rbp_mrl_u
);
594 node
= RotateLeft(aNode
);
595 rbp_mrl_t
= aNode
.Right();
596 if (rbp_mrl_t
.IsRed()) {
597 rbp_mrl_t
.SetColor(NodeColor::Black
);
598 aNode
.SetColor(NodeColor::Red
);
599 rbp_mrl_t
= RotateLeft(aNode
);
600 node
.SetLeft(rbp_mrl_t
);
602 aNode
.SetColor(NodeColor::Black
);
605 aNode
.SetColor(NodeColor::Red
);
606 node
= RotateLeft(aNode
);
611 TreeNode
MoveRedRight(TreeNode aNode
) {
614 rbp_mrr_t
= aNode
.Left();
615 if (rbp_mrr_t
.IsRed()) {
616 TreeNode rbp_mrr_u
, rbp_mrr_v
;
617 rbp_mrr_u
= rbp_mrr_t
.Right();
618 rbp_mrr_v
= rbp_mrr_u
.Left();
619 if (rbp_mrr_v
.IsRed()) {
620 rbp_mrr_u
.SetColor(aNode
.Color());
621 rbp_mrr_v
.SetColor(NodeColor::Black
);
622 rbp_mrr_u
= RotateLeft(rbp_mrr_t
);
623 aNode
.SetLeft(rbp_mrr_u
);
624 node
= RotateRight(aNode
);
625 rbp_mrr_t
= RotateLeft(aNode
);
626 node
.SetRight(rbp_mrr_t
);
628 rbp_mrr_t
.SetColor(aNode
.Color());
629 rbp_mrr_u
.SetColor(NodeColor::Red
);
630 node
= RotateRight(aNode
);
631 rbp_mrr_t
= RotateLeft(aNode
);
632 node
.SetRight(rbp_mrr_t
);
634 aNode
.SetColor(NodeColor::Red
);
636 rbp_mrr_t
.SetColor(NodeColor::Red
);
637 rbp_mrr_t
= rbp_mrr_t
.Left();
638 if (rbp_mrr_t
.IsRed()) {
639 rbp_mrr_t
.SetColor(NodeColor::Black
);
640 node
= RotateRight(aNode
);
641 rbp_mrr_t
= RotateLeft(aNode
);
642 node
.SetRight(rbp_mrr_t
);
644 node
= RotateLeft(aNode
);
650 // The iterator simulates recursion via an array of pointers that store the
651 // current path. This is critical to performance, since a series of calls to
652 // rb_{next,prev}() would require time proportional to (n lg n), whereas this
653 // implementation only requires time proportional to (n).
655 // Since the iterator caches a path down the tree, any tree modification may
656 // cause the cached path to become invalid. Don't modify the tree during an
659 // Size the path arrays such that they are always large enough, even if a
660 // tree consumes all of memory. Since each node must contain a minimum of
661 // two pointers, there can never be more nodes than:
663 // 1 << ((sizeof(void*)<<3) - (log2(sizeof(void*))+1))
665 // Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
668 // (3 * ((sizeof(void*)<<3) - (log2(sizeof(void*))+1)))
670 // This works out to a maximum depth of 87 and 180 for 32- and 64-bit
671 // systems, respectively (approximately 348 and 1440 bytes, respectively).
674 TreeNode mPath
[3 * ((sizeof(void*) << 3) - (LOG2(sizeof(void*)) + 1))];
678 explicit Iterator(RedBlackTree
<T
, Trait
>* aTree
) : mDepth(0) {
679 // Initialize the path to contain the left spine.
682 mPath
[mDepth
++] = aTree
->mRoot
;
683 while ((node
= mPath
[mDepth
- 1].Left())) {
684 mPath
[mDepth
++] = node
;
689 template <typename Iterator
>
695 Item(Iterator
* aIterator
, T
* aItem
)
696 : mIterator(aIterator
), mItem(aItem
) {}
698 bool operator!=(const Item
& aOther
) const {
699 return (mIterator
!= aOther
.mIterator
) || (mItem
!= aOther
.mItem
);
702 T
* operator*() const { return mItem
; }
704 const Item
& operator++() {
705 mItem
= mIterator
->Next();
710 Item
<Iterator
> begin() {
711 return Item
<Iterator
>(this,
712 mDepth
> 0 ? mPath
[mDepth
- 1].Get() : nullptr);
715 Item
<Iterator
> end() { return Item
<Iterator
>(this, nullptr); }
719 if ((node
= mPath
[mDepth
- 1].Right())) {
720 // The successor is the left-most node in the right subtree.
721 mPath
[mDepth
++] = node
;
722 while ((node
= mPath
[mDepth
- 1].Left())) {
723 mPath
[mDepth
++] = node
;
726 // The successor is above the current node. Unwind until a
727 // left-leaning edge is removed from the path, of the path is empty.
728 for (mDepth
--; mDepth
> 0; mDepth
--) {
729 if (mPath
[mDepth
- 1].Left() == mPath
[mDepth
]) {
734 return mDepth
> 0 ? mPath
[mDepth
- 1].Get() : nullptr;
738 Iterator
iter() { return Iterator(this); }