123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754 |
- #pragma once
- #include <util/generic/noncopyable.h>
- template <class T, class C>
- struct TAvlTreeItem;
- template <class T, class C>
- class TAvlTree: public TNonCopyable {
- using TTreeItem = TAvlTreeItem<T, C>;
- friend struct TAvlTreeItem<T, C>;
- static inline const T* AsT(const TTreeItem* item) noexcept {
- return (const T*)item;
- }
- static inline T* AsT(TTreeItem* item) noexcept {
- return (T*)item;
- }
- template <class TTreeItem, class TValue>
- class TIteratorBase {
- public:
- inline TIteratorBase(TTreeItem* p, const TAvlTree* t) noexcept
- : Ptr_(p)
- , Tree_(t)
- {
- }
- inline bool IsEnd() const noexcept {
- return Ptr_ == nullptr;
- }
- inline bool IsBegin() const noexcept {
- return Ptr_ == nullptr;
- }
- inline bool IsFirst() const noexcept {
- return Ptr_ && Ptr_ == Tree_->Head_;
- }
- inline bool IsLast() const noexcept {
- return Ptr_ && Ptr_ == Tree_->Tail_;
- }
- inline TValue& operator*() const noexcept {
- return *AsT(Ptr_);
- }
- inline TValue* operator->() const noexcept {
- return AsT(Ptr_);
- }
- inline TTreeItem* Inc() noexcept {
- return Ptr_ = FindNext(Ptr_);
- }
- inline TTreeItem* Dec() noexcept {
- return Ptr_ = FindPrev(Ptr_);
- }
- inline TIteratorBase& operator++() noexcept {
- Inc();
- return *this;
- }
- inline TIteratorBase operator++(int) noexcept {
- TIteratorBase ret(*this);
- Inc();
- return ret;
- }
- inline TIteratorBase& operator--() noexcept {
- Dec();
- return *this;
- }
- inline TIteratorBase operator--(int) noexcept {
- TIteratorBase ret(*this);
- Dec();
- return ret;
- }
- inline TIteratorBase Next() const noexcept {
- return ConstructNext(*this);
- }
- inline TIteratorBase Prev() const noexcept {
- return ConstructPrev(*this);
- }
- inline bool operator==(const TIteratorBase& r) const noexcept {
- return Ptr_ == r.Ptr_;
- }
- inline bool operator!=(const TIteratorBase& r) const noexcept {
- return Ptr_ != r.Ptr_;
- }
- private:
- inline static TIteratorBase ConstructNext(const TIteratorBase& i) noexcept {
- return TIterator(FindNext(i.Ptr_), i.Tree_);
- }
- inline static TIteratorBase ConstructPrev(const TIteratorBase& i) noexcept {
- return TIterator(FindPrev(i.Ptr_), i.Tree_);
- }
- inline static TIteratorBase FindPrev(TTreeItem* el) noexcept {
- if (el->Left_ != nullptr) {
- el = el->Left_;
- while (el->Right_ != nullptr) {
- el = el->Right_;
- }
- } else {
- while (true) {
- TTreeItem* last = el;
- el = el->Parent_;
- if (el == nullptr || el->Right_ == last) {
- break;
- }
- }
- }
- return el;
- }
- static TTreeItem* FindNext(TTreeItem* el) {
- if (el->Right_ != nullptr) {
- el = el->Right_;
- while (el->Left_) {
- el = el->Left_;
- }
- } else {
- while (true) {
- TTreeItem* last = el;
- el = el->Parent_;
- if (el == nullptr || el->Left_ == last) {
- break;
- }
- }
- }
- return el;
- }
- private:
- TTreeItem* Ptr_;
- const TAvlTree* Tree_;
- };
- using TConstIterator = TIteratorBase<const TTreeItem, const T>;
- using TIterator = TIteratorBase<TTreeItem, T>;
- static inline TConstIterator ConstructFirstConst(const TAvlTree* t) noexcept {
- return TConstIterator(t->Head_, t);
- }
- static inline TIterator ConstructFirst(const TAvlTree* t) noexcept {
- return TIterator(t->Head_, t);
- }
- static inline TConstIterator ConstructLastConst(const TAvlTree* t) noexcept {
- return TConstIterator(t->Tail_, t);
- }
- static inline TIterator ConstructLast(const TAvlTree* t) noexcept {
- return TIterator(t->Tail_, t);
- }
- static inline bool Compare(const TTreeItem& l, const TTreeItem& r) {
- return C::Compare(*AsT(&l), *AsT(&r));
- }
- public:
- using const_iterator = TConstIterator;
- using iterator = TIterator;
- inline TAvlTree() noexcept
- : Root_(nullptr)
- , Head_(nullptr)
- , Tail_(nullptr)
- {
- }
- inline ~TAvlTree() noexcept {
- Clear();
- }
- inline void Clear() noexcept {
- for (iterator it = Begin(); it != End();) {
- (it++)->TTreeItem::Unlink();
- }
- }
- inline T* Insert(TTreeItem* el, TTreeItem** lastFound = nullptr) noexcept {
- el->Unlink();
- el->Tree_ = this;
- TTreeItem* curEl = Root_;
- TTreeItem* parentEl = nullptr;
- TTreeItem* lastLess = nullptr;
- while (true) {
- if (curEl == nullptr) {
- AttachRebal(el, parentEl, lastLess);
- if (lastFound != nullptr) {
- *lastFound = el;
- }
- return AsT(el);
- }
- if (Compare(*el, *curEl)) {
- parentEl = lastLess = curEl;
- curEl = curEl->Left_;
- } else if (Compare(*curEl, *el)) {
- parentEl = curEl;
- curEl = curEl->Right_;
- } else {
- if (lastFound != nullptr) {
- *lastFound = curEl;
- }
- return nullptr;
- }
- }
- }
- inline T* Find(const TTreeItem* el) const noexcept {
- TTreeItem* curEl = Root_;
- while (curEl) {
- if (Compare(*el, *curEl)) {
- curEl = curEl->Left_;
- } else if (Compare(*curEl, *el)) {
- curEl = curEl->Right_;
- } else {
- return AsT(curEl);
- }
- }
- return nullptr;
- }
- inline T* LowerBound(const TTreeItem* el) const noexcept {
- TTreeItem* curEl = Root_;
- TTreeItem* lowerBound = nullptr;
- while (curEl) {
- if (Compare(*el, *curEl)) {
- lowerBound = curEl;
- curEl = curEl->Left_;
- } else if (Compare(*curEl, *el)) {
- curEl = curEl->Right_;
- } else {
- return AsT(curEl);
- }
- }
- return AsT(lowerBound);
- }
- inline T* Erase(TTreeItem* el) noexcept {
- if (el->Tree_ == this) {
- return this->EraseImpl(el);
- }
- return nullptr;
- }
- inline T* EraseImpl(TTreeItem* el) noexcept {
- el->Tree_ = nullptr;
- TTreeItem* replacement;
- TTreeItem* fixfrom;
- long lheight, rheight;
- if (el->Right_) {
- replacement = el->Right_;
- while (replacement->Left_) {
- replacement = replacement->Left_;
- }
- if (replacement->Parent_ == el) {
- fixfrom = replacement;
- } else {
- fixfrom = replacement->Parent_;
- }
- if (el == Head_) {
- Head_ = replacement;
- }
- RemoveEl(replacement, replacement->Right_);
- ReplaceEl(el, replacement);
- } else if (el->Left_) {
- replacement = el->Left_;
- while (replacement->Right_) {
- replacement = replacement->Right_;
- }
- if (replacement->Parent_ == el) {
- fixfrom = replacement;
- } else {
- fixfrom = replacement->Parent_;
- }
- if (el == Tail_) {
- Tail_ = replacement;
- }
- RemoveEl(replacement, replacement->Left_);
- ReplaceEl(el, replacement);
- } else {
- fixfrom = el->Parent_;
- if (el == Head_) {
- Head_ = el->Parent_;
- }
- if (el == Tail_) {
- Tail_ = el->Parent_;
- }
- RemoveEl(el, nullptr);
- }
- if (fixfrom == nullptr) {
- return AsT(el);
- }
- RecalcHeights(fixfrom);
- TTreeItem* ub = FindFirstUnbalEl(fixfrom);
- while (ub) {
- lheight = ub->Left_ ? ub->Left_->Height_ : 0;
- rheight = ub->Right_ ? ub->Right_->Height_ : 0;
- if (rheight > lheight) {
- ub = ub->Right_;
- lheight = ub->Left_ ? ub->Left_->Height_ : 0;
- rheight = ub->Right_ ? ub->Right_->Height_ : 0;
- if (rheight > lheight) {
- ub = ub->Right_;
- } else if (rheight < lheight) {
- ub = ub->Left_;
- } else {
- ub = ub->Right_;
- }
- } else {
- ub = ub->Left_;
- lheight = ub->Left_ ? ub->Left_->Height_ : 0;
- rheight = ub->Right_ ? ub->Right_->Height_ : 0;
- if (rheight > lheight) {
- ub = ub->Right_;
- } else if (rheight < lheight) {
- ub = ub->Left_;
- } else {
- ub = ub->Left_;
- }
- }
- fixfrom = Rebalance(ub);
- ub = FindFirstUnbalEl(fixfrom);
- }
- return AsT(el);
- }
- inline const_iterator First() const noexcept {
- return ConstructFirstConst(this);
- }
- inline const_iterator Last() const noexcept {
- return ConstructLastConst(this);
- }
- inline const_iterator Begin() const noexcept {
- return First();
- }
- inline const_iterator End() const noexcept {
- return const_iterator(nullptr, this);
- }
- inline const_iterator begin() const noexcept {
- return Begin();
- }
- inline const_iterator end() const noexcept {
- return End();
- }
- inline const_iterator cbegin() const noexcept {
- return Begin();
- }
- inline const_iterator cend() const noexcept {
- return End();
- }
- inline iterator First() noexcept {
- return ConstructFirst(this);
- }
- inline iterator Last() noexcept {
- return ConstructLast(this);
- }
- inline iterator Begin() noexcept {
- return First();
- }
- inline iterator End() noexcept {
- return iterator(nullptr, this);
- }
- inline iterator begin() noexcept {
- return Begin();
- }
- inline iterator end() noexcept {
- return End();
- }
- inline bool Empty() const noexcept {
- return const_cast<TAvlTree*>(this)->Begin() == const_cast<TAvlTree*>(this)->End();
- }
- inline explicit operator bool() const noexcept {
- return !this->Empty();
- }
- template <class Functor>
- inline void ForEach(Functor& f) {
- iterator it = Begin();
- while (!it.IsEnd()) {
- iterator next = it;
- ++next;
- f(*it);
- it = next;
- }
- }
- private:
- inline TTreeItem* Rebalance(TTreeItem* n) noexcept {
- long lheight, rheight;
- TTreeItem* a;
- TTreeItem* b;
- TTreeItem* c;
- TTreeItem* t1;
- TTreeItem* t2;
- TTreeItem* t3;
- TTreeItem* t4;
- TTreeItem* p = n->Parent_;
- TTreeItem* gp = p->Parent_;
- TTreeItem* ggp = gp->Parent_;
- if (gp->Right_ == p) {
- if (p->Right_ == n) {
- a = gp;
- b = p;
- c = n;
- t1 = gp->Left_;
- t2 = p->Left_;
- t3 = n->Left_;
- t4 = n->Right_;
- } else {
- a = gp;
- b = n;
- c = p;
- t1 = gp->Left_;
- t2 = n->Left_;
- t3 = n->Right_;
- t4 = p->Right_;
- }
- } else {
- if (p->Right_ == n) {
- a = p;
- b = n;
- c = gp;
- t1 = p->Left_;
- t2 = n->Left_;
- t3 = n->Right_;
- t4 = gp->Right_;
- } else {
- a = n;
- b = p;
- c = gp;
- t1 = n->Left_;
- t2 = n->Right_;
- t3 = p->Right_;
- t4 = gp->Right_;
- }
- }
- if (ggp == nullptr) {
- Root_ = b;
- } else if (ggp->Left_ == gp) {
- ggp->Left_ = b;
- } else {
- ggp->Right_ = b;
- }
- b->Parent_ = ggp;
- b->Left_ = a;
- a->Parent_ = b;
- b->Right_ = c;
- c->Parent_ = b;
- a->Left_ = t1;
- if (t1 != nullptr) {
- t1->Parent_ = a;
- }
- a->Right_ = t2;
- if (t2 != nullptr) {
- t2->Parent_ = a;
- }
- c->Left_ = t3;
- if (t3 != nullptr) {
- t3->Parent_ = c;
- }
- c->Right_ = t4;
- if (t4 != nullptr) {
- t4->Parent_ = c;
- }
- lheight = a->Left_ ? a->Left_->Height_ : 0;
- rheight = a->Right_ ? a->Right_->Height_ : 0;
- a->Height_ = (lheight > rheight ? lheight : rheight) + 1;
- lheight = c->Left_ ? c->Left_->Height_ : 0;
- rheight = c->Right_ ? c->Right_->Height_ : 0;
- c->Height_ = (lheight > rheight ? lheight : rheight) + 1;
- lheight = a->Height_;
- rheight = c->Height_;
- b->Height_ = (lheight > rheight ? lheight : rheight) + 1;
- RecalcHeights(ggp);
- return ggp;
- }
- inline void RecalcHeights(TTreeItem* el) noexcept {
- long lheight, rheight, new_height;
- while (el) {
- lheight = el->Left_ ? el->Left_->Height_ : 0;
- rheight = el->Right_ ? el->Right_->Height_ : 0;
- new_height = (lheight > rheight ? lheight : rheight) + 1;
- if (new_height == el->Height_) {
- return;
- } else {
- el->Height_ = new_height;
- }
- el = el->Parent_;
- }
- }
- inline TTreeItem* FindFirstUnbalGP(TTreeItem* el) noexcept {
- long lheight, rheight, balanceProp;
- TTreeItem* gp;
- if (el == nullptr || el->Parent_ == nullptr || el->Parent_->Parent_ == nullptr) {
- return nullptr;
- }
- gp = el->Parent_->Parent_;
- while (gp != nullptr) {
- lheight = gp->Left_ ? gp->Left_->Height_ : 0;
- rheight = gp->Right_ ? gp->Right_->Height_ : 0;
- balanceProp = lheight - rheight;
- if (balanceProp < -1 || balanceProp > 1) {
- return el;
- }
- el = el->Parent_;
- gp = gp->Parent_;
- }
- return nullptr;
- }
- inline TTreeItem* FindFirstUnbalEl(TTreeItem* el) noexcept {
- if (el == nullptr) {
- return nullptr;
- }
- while (el) {
- const long lheight = el->Left_ ? el->Left_->Height_ : 0;
- const long rheight = el->Right_ ? el->Right_->Height_ : 0;
- const long balanceProp = lheight - rheight;
- if (balanceProp < -1 || balanceProp > 1) {
- return el;
- }
- el = el->Parent_;
- }
- return nullptr;
- }
- inline void ReplaceEl(TTreeItem* el, TTreeItem* replacement) noexcept {
- TTreeItem* parent = el->Parent_;
- TTreeItem* left = el->Left_;
- TTreeItem* right = el->Right_;
- replacement->Left_ = left;
- if (left) {
- left->Parent_ = replacement;
- }
- replacement->Right_ = right;
- if (right) {
- right->Parent_ = replacement;
- }
- replacement->Parent_ = parent;
- if (parent) {
- if (parent->Left_ == el) {
- parent->Left_ = replacement;
- } else {
- parent->Right_ = replacement;
- }
- } else {
- Root_ = replacement;
- }
- replacement->Height_ = el->Height_;
- }
- inline void RemoveEl(TTreeItem* el, TTreeItem* filler) noexcept {
- TTreeItem* parent = el->Parent_;
- if (parent) {
- if (parent->Left_ == el) {
- parent->Left_ = filler;
- } else {
- parent->Right_ = filler;
- }
- } else {
- Root_ = filler;
- }
- if (filler) {
- filler->Parent_ = parent;
- }
- return;
- }
- inline void AttachRebal(TTreeItem* el, TTreeItem* parentEl, TTreeItem* lastLess) {
- el->Parent_ = parentEl;
- el->Left_ = nullptr;
- el->Right_ = nullptr;
- el->Height_ = 1;
- if (parentEl != nullptr) {
- if (lastLess == parentEl) {
- parentEl->Left_ = el;
- } else {
- parentEl->Right_ = el;
- }
- if (Head_->Left_ == el) {
- Head_ = el;
- }
- if (Tail_->Right_ == el) {
- Tail_ = el;
- }
- } else {
- Root_ = el;
- Head_ = Tail_ = el;
- }
- RecalcHeights(parentEl);
- TTreeItem* ub = FindFirstUnbalGP(el);
- if (ub != nullptr) {
- Rebalance(ub);
- }
- }
- private:
- TTreeItem* Root_;
- TTreeItem* Head_;
- TTreeItem* Tail_;
- };
- template <class T, class C>
- struct TAvlTreeItem: public TNonCopyable {
- public:
- using TTree = TAvlTree<T, C>;
- friend class TAvlTree<T, C>;
- friend typename TAvlTree<T, C>::TConstIterator;
- friend typename TAvlTree<T, C>::TIterator;
- inline TAvlTreeItem() noexcept
- : Left_(nullptr)
- , Right_(nullptr)
- , Parent_(nullptr)
- , Height_(0)
- , Tree_(nullptr)
- {
- }
- inline ~TAvlTreeItem() noexcept {
- Unlink();
- }
- inline void Unlink() noexcept {
- if (Tree_) {
- Tree_->EraseImpl(this);
- }
- }
- private:
- TAvlTreeItem* Left_;
- TAvlTreeItem* Right_;
- TAvlTreeItem* Parent_;
- long Height_;
- TTree* Tree_;
- };
|