| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- //
- // Urho3D Engine
- // Copyright (c) 2008-2012 Lasse Öörni
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- #pragma once
- #include "Allocator.h"
- #include "Swap.h"
- // Based on Red Black Trees by Julienne Walker
- // http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
- /// Red-black tree node base.
- struct TreeNodeBase
- {
- /// Construct.
- TreeNodeBase() :
- parent_(0),
- isRed_(true)
- {
- link_[0] = 0;
- link_[1] = 0;
- }
-
- /// %Set a child link, adjusting the child's parent as necessary.
- void SetChild(unsigned dir, TreeNodeBase* newChild)
- {
- link_[dir] = newChild;
- if (newChild)
- newChild->parent_ = this;
- }
-
- /// Child links.
- TreeNodeBase* link_[2];
- /// Parent node.
- TreeNodeBase* parent_;
- /// Color flag.
- bool isRed_;
- };
- /// Red-black tree iterator base class.
- class TreeIteratorBase
- {
- public:
- /// Construct.
- TreeIteratorBase() :
- ptr_(0),
- prev_(0)
- {
- }
-
- /// Construct with a node pointer.
- explicit TreeIteratorBase(TreeNodeBase* ptr) :
- ptr_(ptr),
- prev_(0)
- {
- }
-
- /// Test for equality with another iterator.
- bool operator == (const TreeIteratorBase& rhs) const { return ptr_ == rhs.ptr_; }
- /// Test for inequality with another iterator.
- bool operator != (const TreeIteratorBase& rhs) const { return ptr_ != rhs.ptr_; }
-
- /// Go to the next node.
- void GotoNext()
- {
- if (!ptr_)
- return;
-
- prev_ = ptr_;
-
- if (!ptr_->link_[1])
- {
- while (ptr_->parent_ && ptr_->parent_->link_[1] == ptr_)
- ptr_ = ptr_->parent_;
-
- ptr_ = ptr_->parent_;
- return;
- }
-
- ptr_ = ptr_->link_[1];
- while (ptr_->link_[0])
- ptr_ = ptr_->link_[0];
- }
-
- /// Go to the previous node.
- void GotoPrev()
- {
- if (!ptr_)
- {
- ptr_ = prev_;
- prev_ = 0;
- return;
- }
-
- prev_ = 0;
-
- if (!ptr_->link_[0])
- {
- while (ptr_->parent_ && ptr_->parent_->link_[0] == ptr_)
- ptr_ = ptr_->parent_;
-
- ptr_ = ptr_->parent_;
- return;
- }
-
- ptr_ = ptr_->link_[0];
- while (ptr_->link_[1])
- ptr_ = ptr_->link_[1];
- }
-
- /// Current node pointer.
- TreeNodeBase* ptr_;
- /// Previous node pointer, needed to go back from the end.
- TreeNodeBase* prev_;
- };
- /// Red-black tree base class.
- class TreeBase
- {
- public:
- /// Construct.
- TreeBase() :
- head_(0),
- allocator_(0),
- size_(0)
- {
- }
-
- /// Swap with another tree.
- void Swap(TreeBase& rhs)
- {
- ::Swap(head_, rhs.head_);
- ::Swap(allocator_, rhs.allocator_);
- ::Swap(size_, rhs.size_);
- }
-
- protected:
- /// Check whether a node is red.
- bool IsRed(TreeNodeBase* node) const { return node && node->isRed_; }
-
- /// Single rotation.
- TreeNodeBase* RotateSingle(TreeNodeBase* node, unsigned dir)
- {
- TreeNodeBase* save = node->link_[!dir];
-
- node->SetChild(!dir, save->link_[dir]);
- save->SetChild(dir, node);
-
- node->isRed_ = true;
- save->isRed_ = false;
-
- return save;
- }
-
- /// Double rotation.
- TreeNodeBase* RotateDouble(TreeNodeBase* node, unsigned dir)
- {
- node->SetChild(!dir, RotateSingle(node->link_[!dir], !dir));
- return RotateSingle(node, dir);
- }
-
- /// Head node.
- TreeNodeBase* head_;
- /// Node allocator.
- AllocatorBlock* allocator_;
- /// Number of nodes.
- unsigned size_;
- };
|