diff --git a/headers/private/kernel/util/AVLTreeMap.h b/headers/private/kernel/util/AVLTreeMap.h index 8057ecf8cd..6cba267141 100644 --- a/headers/private/kernel/util/AVLTreeMap.h +++ b/headers/private/kernel/util/AVLTreeMap.h @@ -1,30 +1,7 @@ -// AVLTreeMap.h -// -// Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de) -// -// 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. -// -// Except as contained in this notice, the name of a copyright holder shall -// not be used in advertising or otherwise to promote the sale, use or other -// dealings in this Software without prior written authorization of the -// copyright holder. - +/* + * Copyright 2003-2007, Ingo Weinhold . + * Distributed under the terms of the MIT License. + */ #ifndef _AVL_TREE_MAP_H #define _AVL_TREE_MAP_H @@ -32,11 +9,203 @@ #include #include -#include "MallocFreeAllocator.h" +#include + // maximal height of a tree static const int kMaxAVLTreeHeight = 32; +class AVLTreeIterator; + + +// AVLTreeNode +struct AVLTreeNode { + AVLTreeNode* parent; + AVLTreeNode* left; + AVLTreeNode* right; + int balance_factor; +}; + + +// AVLTreeCompare +class AVLTreeCompare { +public: + virtual ~AVLTreeCompare(); + + virtual int CompareKeyNode(const void* key, + const AVLTreeNode* node) = 0; + virtual int CompareNodes(const AVLTreeNode* node1, + const AVLTreeNode* node2) = 0; +}; + + +// AVLTree +class AVLTree { +public: + AVLTree(AVLTreeCompare* compare); + ~AVLTree(); + + inline int Count() const { return fNodeCount; } + inline bool IsEmpty() const { return (fNodeCount == 0); } + void MakeEmpty(); + + inline AVLTreeNode* Root() const { return fRoot; } + + AVLTreeNode* LeftMost(AVLTreeNode* node) const; + AVLTreeNode* RightMost(AVLTreeNode* node) const; + + AVLTreeNode* Previous(AVLTreeNode* node) const; + AVLTreeNode* Next(AVLTreeNode* node) const; + + inline AVLTreeIterator GetIterator() const; + inline AVLTreeIterator GetIterator(AVLTreeNode* node) const; + + AVLTreeNode* Find(const void* key); + AVLTreeNode* FindClose(const void* key, bool less); + + status_t Insert(AVLTreeNode* element); + AVLTreeNode* Remove(const void* key); + bool Remove(AVLTreeNode* element); + +private: + enum { + NOT_FOUND = -3, + DUPLICATE = -2, + NO_MEMORY = -1, + OK = 0, + HEIGHT_CHANGED = 1, + + LEFT = -1, + BALANCED = 0, + RIGHT = 1, + }; + + // rotations + void _RotateRight(AVLTreeNode** nodeP); + void _RotateLeft(AVLTreeNode** nodeP); + + // insert + int _BalanceInsertLeft(AVLTreeNode** node); + int _BalanceInsertRight(AVLTreeNode** node); + int _Insert(AVLTreeNode* nodeToInsert); + + // remove + int _BalanceRemoveLeft(AVLTreeNode** node); + int _BalanceRemoveRight(AVLTreeNode** node); + int _RemoveRightMostChild(AVLTreeNode** node, + AVLTreeNode** foundNode); + int _Remove(AVLTreeNode* node); + + AVLTreeNode* fRoot; + int fNodeCount; + AVLTreeCompare* fCompare; +}; + + +// AVLTreeIterator +class AVLTreeIterator { +public: + inline AVLTreeIterator() + : fParent(NULL), + fCurrent(NULL), + fNext(NULL) + { + } + + inline AVLTreeIterator(const AVLTreeIterator& other) + : fParent(other.fParent), + fCurrent(other.fCurrent), + fNext(other.fNext) + { + } + + inline AVLTreeNode* Current() const + { + return fCurrent; + } + + inline bool HasNext() const + { + return fNext; + } + + inline AVLTreeNode* Next() + { + fCurrent = fNext; + + if (fNext) + fNext = fParent->Next(fNext); + + return fCurrent; + } + + inline AVLTreeNode* Previous() + { + if (fCurrent) { + fNext = fCurrent; + fCurrent = fParent->Previous(fCurrent); + } else if (fNext) + fCurrent = fParent->Previous(fNext); + + return fCurrent; + } + + inline AVLTreeNode* Remove() + { + if (!fCurrent) + return NULL; + + AVLTreeNode* node = fCurrent; + fCurrent = NULL; + + return (const_cast(fParent)->Remove(node) ? node : NULL); + } + + inline AVLTreeIterator& operator=(const AVLTreeIterator& other) + { + fParent = other.fParent; + fCurrent = other.fCurrent; + fNext = other.fNext; + return *this; + } + +private: + inline AVLTreeIterator(const AVLTree* parent, AVLTreeNode* current, + AVLTreeNode* next) + : fParent(parent), + fCurrent(current), + fNext(next) + { + } + +protected: + friend class AVLTree; + + const AVLTree* fParent; + AVLTreeNode* fCurrent; + AVLTreeNode* fNext; +}; + + +// GetIterator +inline AVLTreeIterator +AVLTree::GetIterator() const +{ + return AVLTreeIterator(this, NULL, LeftMost(fRoot)); +} + + +// GetIterator +inline AVLTreeIterator +AVLTree::GetIterator(AVLTreeNode* node) const +{ + return AVLTreeIterator(this, node, Next(node)); +} + + +// #pragma mark - AVLTreeMap and friends + + // strategies namespace AVLTreeMapStrategy { // key orders @@ -49,1305 +218,457 @@ namespace AVLTreeMapStrategy { template class Allocator = MallocFreeAllocator> class Auto; - //! User managed node strategy (user is responsible for node allocation/deallocation) -// template -// class User; - -// NodeStrategy::Node must implement this interface. -// struct Node { -// Node *parent; -// Node *left; -// Node *right; -// int balance_factor; -// }; +/*! NodeStrategy must implement this interface: + typename Node; + inline Node* Allocate(const Key& key, const Value& value) + inline void Free(Node* node) + inline Key GetKey(Node* node) const + inline Value& GetValue(Node* node) const + inline AVLTreeNode* GetAVLTreeNode(Node* node) const + inline Node* GetNode(AVLTreeNode* node) const + inline int CompareKeyNode(const Key& a, const Node* b) + inline int CompareNodes(const Node* a, const Node* b) +*/ } -template class AVLTreeMapIterator; -template class AVLTreeMapEntry; -template class AVLTreeMapEntryPointer; // for convenience #define _AVL_TREE_MAP_TEMPLATE_LIST template + typename NodeStrategy> #define _AVL_TREE_MAP_CLASS_NAME AVLTreeMap + // AVLTreeMap template > -class AVLTreeMap { +class AVLTreeMap : protected AVLTreeCompare { private: typedef typename NodeStrategy::Node Node; typedef _AVL_TREE_MAP_CLASS_NAME Class; - typedef AVLTreeMapEntry Entry; public: - class Entry; class Iterator; class ConstIterator; public: - AVLTreeMap(); - ~AVLTreeMap(); + AVLTreeMap(const NodeStrategy& strategy + = NodeStrategy()); + virtual ~AVLTreeMap(); - inline int Count() const { return fNodeCount; } - inline bool IsEmpty() const { return (fNodeCount == 0); } - void MakeEmpty(); + inline int Count() const { return fTree.Count(); } + inline bool IsEmpty() const { return fTree.IsEmpty(); } + inline void MakeEmpty(); - inline Iterator Begin() { return ++Iterator(this, NULL); } - inline ConstIterator Begin() const { return ++ConstIterator(this, NULL); } - inline Iterator End() { return Iterator(this, NULL); } - inline ConstIterator End() const { return ConstIterator(this, NULL); } - inline Iterator Null() { return Iterator(this, NULL); } - inline ConstIterator Null() const { return ConstIterator(this, NULL); } + Node* RootNode() const; - Iterator Find(const Key &key); - Iterator FindClose(const Key &key, bool less); + inline Iterator GetIterator(); + inline ConstIterator GetIterator() const; - status_t Insert(const Key &key, const Value &value, Iterator &iterator); - status_t Remove(const Key &key); - Iterator Erase(const Iterator &iterator); + inline Iterator GetIterator(Node* node); + inline ConstIterator GetIterator(Node* node) const; - // debugging - int Check(Node *node = NULL, int level = 0, bool levelsOnly = false) const; + Iterator Find(const Key& key); + Iterator FindClose(const Key& key, bool less); + + status_t Insert(const Key& key, const Value& value, + Iterator* iterator); + status_t Remove(const Key& key); + + const NodeStrategy& GetNodeStrategy() const { return fStrategy; } protected: - enum { - NOT_FOUND = -3, - DUPLICATE = -2, - NO_MEMORY = -1, - OK = 0, - HEIGHT_CHANGED = 1, + // AVLTreeCompare + virtual int CompareKeyNode(const void* key, + const AVLTreeNode* node); + virtual int CompareNodes(const AVLTreeNode* node1, + const AVLTreeNode* node2); - LEFT = -1, - BALANCED = 0, - RIGHT = 1, - }; - - // rotations - void _RotateRight(Node **nodeP); - void _RotateLeft(Node **nodeP); - - // insert - int _BalanceInsertLeft(Node **node); - int _BalanceInsertRight(Node **node); - int _Insert(const Key &key, const Value &value, Node **node, - Iterator *iterator); - - // remove - int _BalanceRemoveLeft(Node **node); - int _BalanceRemoveRight(Node **node); - int _RemoveRightMostChild(Node **node, Node **foundNode); - int _Remove(const Key &key, Node **node); - int _Remove(Node *node); - - void _FreeTree(Node *node); - - // debugging - void _DumpNode(Node *node) const; + void _FreeTree(AVLTreeNode* node); // strategy shortcuts - inline Node *Allocate(const Key &key, const Value &value); - inline void Free(Node *node); - inline Key &GetKey(Node *node) const; - inline Value &GetValue(Node *node) const; - inline int Compare(const Key &a, const Key &b); + inline Node* _Allocate(const Key& key, const Value& value); + inline void _Free(Node* node); + inline Key& _GetKey(Node* node) const; + inline Value& _GetValue(Node* node) const; + inline AVLTreeNode* _GetAVLTreeNode(const Node* node) const; + inline Node* _GetNode(const AVLTreeNode* node) const; + inline int _CompareKeyNode(const Key& a, const Node* b); + inline int _CompareNodes(const Node* a, const Node* b); protected: - friend class Entry; - friend class Iterator; - friend class ConstIterator; - friend AVLTreeMapIterator; - friend AVLTreeMapIterator; + friend class Iterator; + friend class ConstIterator; - Node *fRoot; - int fNodeCount; - NodeStrategy fStrategy; + AVLTree fTree; + NodeStrategy fStrategy; +public: // Iterator - class Iterator : public AVLTreeMapIterator<_AVL_TREE_MAP_CLASS_NAME> { - private: - typedef AVLTreeMapIterator<_AVL_TREE_MAP_CLASS_NAME> SuperClass; - + // (need to implement it here, otherwise gcc 2.95.3 chokes) + class Iterator : public ConstIterator { public: - inline Iterator(); - inline Iterator(const Iterator &other); - - inline Iterator &operator++(); - inline Iterator operator++(int); - inline Iterator &operator--(); - inline Iterator operator--(int); - inline Iterator &operator=(Iterator &other); - + inline Iterator() + : ConstIterator() + { + } + + inline Iterator(const Iterator& other) + : ConstIterator(other) + { + } + + inline void Remove() + { + if (AVLTreeNode* node = ConstIterator::fTreeIterator.Remove()) { + _AVL_TREE_MAP_CLASS_NAME* parent + = const_cast<_AVL_TREE_MAP_CLASS_NAME*>( + ConstIterator::fParent); + parent->_Free(parent->_GetNode(node)); + } + } + private: - inline Iterator(_AVL_TREE_MAP_CLASS_NAME *parent, Node *node = NULL); - - friend class _AVL_TREE_MAP_CLASS_NAME; - }; - - // ConstIterator - class ConstIterator - : public AVLTreeMapIterator { - private: - typedef AVLTreeMapIterator SuperClass; - - public: - inline ConstIterator(); - inline ConstIterator(const ConstIterator &other); - inline ConstIterator(const Iterator &other); - - inline ConstIterator &operator++(); - inline ConstIterator operator++(int); - inline ConstIterator &operator--(); - inline ConstIterator operator--(int); - inline ConstIterator &operator=(ConstIterator &other); - inline ConstIterator &operator=(Iterator &other); - - private: - inline ConstIterator(const _AVL_TREE_MAP_CLASS_NAME *parent, - Node *node = NULL); - + inline Iterator(_AVL_TREE_MAP_CLASS_NAME* parent, + const AVLTreeIterator& treeIterator) + : ConstIterator(parent, treeIterator) + { + } + friend class _AVL_TREE_MAP_CLASS_NAME; }; }; -// AVLTreeMapEntry -template -class AVLTreeMapEntry { -public: - AVLTreeMapEntry() - : fParent(NULL), fNode(NULL) {} - AVLTreeMapEntry(const AVLTreeMapEntry &other) - : fParent(other.fParent), fNode(other.fNode) {} - - inline const Parent::Key &Key() const - { return fParent->GetKey(fNode); } - inline const Parent::Value &Value() const - { return fParent->GetValue(fNode); } - -private: - AVLTreeMapEntry(const Parent *parent, Parent::Node *node) - : fParent(parent), fNode(node) {} - -private: - friend class AVLTreeMapEntryPointer; - friend class AVLTreeMapIterator; - friend class AVLTreeMapIterator; - - const Parent *fParent; - Parent::Node *fNode; -}; - -// AVLTreeMapEntryPointer -template -class AVLTreeMapEntryPointer { -public: - inline const Entry *operator->() const - { - return &fEntry; - } - -private: - AVLTreeMapEntryPointer(const Parent *parent, Parent::Node *node) - : fEntry(parent, node) {} - - AVLTreeMapEntryPointer(const AVLTreeMapEntryPointer &); - AVLTreeMapEntryPointer &operator=(const AVLTreeMapEntryPointer &); - -private: - friend class AVLTreeMapIterator; - friend class AVLTreeMapIterator; - - AVLTreeMapEntry fEntry; -}; - -// AVLTreeMapIterator -template -class AVLTreeMapIterator { -private: - typedef AVLTreeMapIterator Iterator; - typedef typename Parent::Node Node; - typedef typename Parent::Entry Entry; - typedef AVLTreeMapEntryPointer EntryPointer; - -public: - inline bool operator==(const Iterator &other) const - { - return (fParent == other.fParent && fCurrent == other.fCurrent); - } - - inline bool operator!=(const Iterator &other) const - { - return !(*this == other); - } - - inline const Entry operator*() const - { - return Entry(fParent, fCurrent); - } - - inline const EntryPointer operator->() const - { - return EntryPointer(fParent, fCurrent); - } - -protected: - inline AVLTreeMapIterator() - : fParent(NULL), - fCurrent(NULL) - { - } - - inline AVLTreeMapIterator(const Iterator &other) - : fParent(other.fParent), - fCurrent(other.fCurrent) - { - } - - inline AVLTreeMapIterator(Parent *parent, Node *node = NULL) - : fParent(parent), - fCurrent(node) - { - } - - inline Iterator &operator++() - { - if (fCurrent) - fCurrent = _GetNextNode(fCurrent); - else if (fParent) - fCurrent = _GetLeftMostNode(fParent->fRoot); - return *this; - } - - inline Iterator operator++(int) - { - Iterator it(*this); - ++*this; - return it; - } - - inline Iterator &operator--() - { - if (fCurrent) - fCurrent = _GetPreviousNode(fCurrent); - else if (fParent) - fCurrent = _GetRightMostNode(fParent->fRoot); - return *this; - } - - inline Iterator operator--(int) - { - Iterator it(*this); - --*this; - return it; - } - - inline Iterator &operator=(const Iterator &other) - { - fParent = other.fParent; - fCurrent = other.fCurrent; - return *this; - } - - inline operator bool() const - { - return fCurrent; - } - -private: - static inline Node *_GetPreviousNode(Node *node) - { - if (node) { - // The previous node cannot be in the right subtree. - if (node->left) { - // We have a left subtree, so go to the right-most node. - node = node->left; - while (node->right) - node = node->right; - } else { - // No left subtree: Backtrack our path and stop, where we - // took the right branch. - Node *previous; - do { - previous = node; - node = node->parent; - } while (node && previous == node->left); - } - } - return node; - } - - static inline Node *_GetNextNode(Node *node) - { - if (node) { - // The next node cannot be in the left subtree. - if (node->right) { - // We have a right subtree, so go to the left-most node. - node = node->right; - while (node->left) - node = node->left; - } else { - // No right subtree: Backtrack our path and stop, where we - // took the left branch. - Node *previous; - do { - previous = node; - node = node->parent; - } while (node && previous == node->right); - } - } - return node; - } - - static inline Node *_GetLeftMostNode(Node *node) - { - if (node) { - while (node->left) - node = node->left; - } - return node; - } - - static inline Node *_GetRightMostNode(Node *node) - { - if (node) { - while (node->right) - node = node->right; - } - return node; - } - -protected: - Parent *fParent; - Node *fCurrent; -}; - -// Iterator - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator::Iterator() - : SuperClass() -{ -} - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator::Iterator(const Iterator &other) - : SuperClass(other) -{ -} - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator & -_AVL_TREE_MAP_CLASS_NAME::Iterator::operator++() -{ - SuperClass::operator++(); - return *this; -} - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator -_AVL_TREE_MAP_CLASS_NAME::Iterator::operator++(int) -{ - Iterator it(*this); - ++*this; - return it; -} - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator & -_AVL_TREE_MAP_CLASS_NAME::Iterator::operator--() -{ - SuperClass::operator--(); - return *this; -} - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator -_AVL_TREE_MAP_CLASS_NAME::Iterator::operator--(int) -{ - Iterator it(*this); - --*this; - return it; -} - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator & -_AVL_TREE_MAP_CLASS_NAME::Iterator::operator=(Iterator &other) -{ - *(SuperClass*)this = other; - return *this; -} - -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Iterator::Iterator(_AVL_TREE_MAP_CLASS_NAME *parent, - Node *node) - : SuperClass(parent, node) -{ -} - // ConstIterator - _AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator() - : SuperClass() -{ -} +class _AVL_TREE_MAP_CLASS_NAME::ConstIterator { +public: + inline ConstIterator() + : fParent(NULL), + fTreeIterator() + { + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator( - const ConstIterator &other) - : SuperClass(other) -{ -} + inline ConstIterator(const ConstIterator& other) + : fParent(other.fParent), + fTreeIterator(other.fTreeIterator) + { + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator(const Iterator &other) - : SuperClass(other.fParent, other.fCurrent) -{ -} + inline bool HasCurrent() const + { + return fTreeIterator.Current(); + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator & -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator++() -{ - SuperClass::operator++(); - return *this; -} + inline Key CurrentKey() + { + if (AVLTreeNode* node = fTreeIterator.Current()) + return fParent->_GetKey(fParent->_GetNode(node)); + return Key(); + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator++(int) -{ - ConstIterator it(*this); - ++*this; - return it; -} + inline Value Current() + { + if (AVLTreeNode* node = fTreeIterator.Current()) + return fParent->_GetValue(fParent->_GetNode(node)); + return Value(); + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator & -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator--() -{ - SuperClass::operator--(); - return *this; -} + inline Value* CurrentValuePointer() + { + if (AVLTreeNode* node = fTreeIterator.Current()) + return &fParent->_GetValue(fParent->_GetNode(node)); + return NULL; + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator--(int) -{ - Iterator it(*this); - --*this; - return it; -} + inline bool HasNext() const + { + return fTreeIterator.HasNext(); + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator & -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator=(ConstIterator &other) -{ - *(SuperClass*)this = other; - return *this; -} + inline Value Next() + { + if (AVLTreeNode* node = fTreeIterator.Next()) + return fParent->_GetValue(fParent->_GetNode(node)); + return Value(); + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator & -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator=(Iterator &other) -{ - fParent = other.fParent; - fCurrent = other.fCurrent; - return *this; -} + inline Value Previous() + { + if (AVLTreeNode* node = fTreeIterator.Previous()) + return fParent->_GetValue(fParent->_GetNode(node)); + return Value(); + } -_AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator( - const _AVL_TREE_MAP_CLASS_NAME *parent, Node *node) - : SuperClass(parent, node) -{ -} + inline ConstIterator& operator=(const ConstIterator& other) + { + fParent = other.fParent; + fTreeIterator = other.fTreeIterator; + return *this; + } +protected: + inline ConstIterator(const _AVL_TREE_MAP_CLASS_NAME* parent, + const AVLTreeIterator& treeIterator) + { + fParent = parent; + fTreeIterator = treeIterator; + } + + friend class _AVL_TREE_MAP_CLASS_NAME; + + const _AVL_TREE_MAP_CLASS_NAME* fParent; + AVLTreeIterator fTreeIterator; +}; -// AVLTreeMap // constructor _AVL_TREE_MAP_TEMPLATE_LIST -_AVL_TREE_MAP_CLASS_NAME::AVLTreeMap() - : fRoot(NULL), - fNodeCount(0) +_AVL_TREE_MAP_CLASS_NAME::AVLTreeMap(const NodeStrategy& strategy) + : fTree(this), + fStrategy(strategy) { } + // destructor _AVL_TREE_MAP_TEMPLATE_LIST _AVL_TREE_MAP_CLASS_NAME::~AVLTreeMap() { - _FreeTree(fRoot); - fRoot = NULL; } + // MakeEmpty _AVL_TREE_MAP_TEMPLATE_LIST -void +inline void _AVL_TREE_MAP_CLASS_NAME::MakeEmpty() { - _FreeTree(fRoot); - fRoot = NULL; - fNodeCount = 0; + AVLTreeNode* root = fTree.Root(); + _FreeTree(root); } + +// RootNode +_AVL_TREE_MAP_TEMPLATE_LIST +inline typename _AVL_TREE_MAP_CLASS_NAME::Node* +_AVL_TREE_MAP_CLASS_NAME::RootNode() const +{ + if (AVLTreeNode* root = fTree.Root()) + return _GetNode(root); + return NULL; +} + + +// GetIterator +_AVL_TREE_MAP_TEMPLATE_LIST +inline typename _AVL_TREE_MAP_CLASS_NAME::Iterator +_AVL_TREE_MAP_CLASS_NAME::GetIterator() +{ + return Iterator(this, fTree.GetIterator()); +} + + +// GetIterator +_AVL_TREE_MAP_TEMPLATE_LIST +inline typename _AVL_TREE_MAP_CLASS_NAME::ConstIterator +_AVL_TREE_MAP_CLASS_NAME::GetIterator() const +{ + return ConstIterator(this, fTree.GetIterator()); +} + + +// GetIterator +_AVL_TREE_MAP_TEMPLATE_LIST +inline typename _AVL_TREE_MAP_CLASS_NAME::Iterator +_AVL_TREE_MAP_CLASS_NAME::GetIterator(Node* node) +{ + return Iterator(this, fTree.GetIterator(_GetAVLTreeNode(node))); +} + + +// GetIterator +_AVL_TREE_MAP_TEMPLATE_LIST +inline typename _AVL_TREE_MAP_CLASS_NAME::ConstIterator +_AVL_TREE_MAP_CLASS_NAME::GetIterator(Node* node) const +{ + return ConstIterator(this, fTree.GetIterator(_GetAVLTreeNode(node))); +} + + // Find _AVL_TREE_MAP_TEMPLATE_LIST -_AVL_TREE_MAP_CLASS_NAME::Iterator -_AVL_TREE_MAP_CLASS_NAME::Find(const Key &key) +typename _AVL_TREE_MAP_CLASS_NAME::Iterator +_AVL_TREE_MAP_CLASS_NAME::Find(const Key& key) { - Node *node = fRoot; - while (node) { - int cmp = Compare(key, GetKey(node)); - if (cmp == 0) - return Iterator(this, node); - if (cmp < 0) - node = node->left; - else - node = node->right; - } - return End(); + if (AVLTreeNode* node = fTree.Find(&key)) + return Iterator(this, fTree.GetIterator(node)); + return Iterator(); } + // FindClose _AVL_TREE_MAP_TEMPLATE_LIST -_AVL_TREE_MAP_CLASS_NAME::Iterator -_AVL_TREE_MAP_CLASS_NAME::FindClose(const Key &key, bool less) +typename _AVL_TREE_MAP_CLASS_NAME::Iterator +_AVL_TREE_MAP_CLASS_NAME::FindClose(const Key& key, bool less) { - Node *node = fRoot; - Node *parent = NULL; - while (node) { - int cmp = Compare(key, GetKey(node)); - if (cmp == 0) - break; - parent = node; - if (cmp < 0) - node = node->left; - else - node = node->right; - } - // not found: try to get close - if (!node && parent) { - node = parent; - int expectedCmp = (less ? -1 : 1); - int cmp = Compare(GetKey(node), key); - if (cmp != expectedCmp) { - // The node's value is less although for a greater value was asked, - // or the other way around. We need to iterate to the next node in - // the right directory. If there is no node, we fail. - if (less) - return ++Iterator(this, node); - return --Iterator(this, node); - } - } - return Iterator(this, node); + if (AVLTreeNode* node = fTree.FindClose(&key, less)) + return Iterator(this, fTree.GetIterator(node)); + return Iterator(); } + // Insert _AVL_TREE_MAP_TEMPLATE_LIST status_t -_AVL_TREE_MAP_CLASS_NAME::Insert(const Key &key, const Value &value, - Iterator &iterator) +_AVL_TREE_MAP_CLASS_NAME::Insert(const Key& key, const Value& value, + Iterator* iterator) { - int result = _Insert(key, value, &fRoot, &iterator); - switch (result) { - case OK: - case HEIGHT_CHANGED: - return B_OK; - case NO_MEMORY: - return B_NO_MEMORY; - case DUPLICATE: - default: - return B_BAD_VALUE; + // allocate a node + Node* userNode = _Allocate(key, value); + if (!userNode) + return B_NO_MEMORY; + + // insert node + AVLTreeNode* node = _GetAVLTreeNode(userNode); + status_t error = fTree.Insert(node); + if (error != B_OK) { + _Free(userNode); + return error; } + + if (iterator) + *iterator = Iterator(this, fTree.GetIterator(node)); + + return B_OK; } + // Remove _AVL_TREE_MAP_TEMPLATE_LIST -ssize_t -_AVL_TREE_MAP_CLASS_NAME::Remove(const Key &key) -{ - // find node - Node *node = fRoot; - while (node) { - int cmp = Compare(key, GetKey(node)); - if (cmp == 0) - break; - else { - if (cmp < 0) - node = node->left; - else - node = node->right; - } - } - // remove it - int result = _Remove(node); - // set result - switch (result) { - case OK: - case HEIGHT_CHANGED: - return 1; - case NOT_FOUND: - default: - return 0; - } -} - -// Erase -_AVL_TREE_MAP_TEMPLATE_LIST -_AVL_TREE_MAP_CLASS_NAME::Iterator -_AVL_TREE_MAP_CLASS_NAME::Erase(const Iterator &iterator) -{ - Iterator it(iterator); - if (Node *node = it._GetCurrentNode()) { - it.GetNext(); - _Remove(node); - return it; - } - return End(); -} - -// Check -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::Check(Node *node, int level, bool levelsOnly) const -{ - int height = 0; - if (node) { - // check root node parent - if (node == fRoot && node->parent != NULL) { - printf("Root node has parent: %p\n", node->parent); - debugger("Root node has parent."); - } - // check children's parents - if (node->left && node->left->parent != node) { - printf("Left child of node has has wrong parent: %p, should be: " - "%p\n", node->left->parent, node); - _DumpNode(node); - debugger("Left child node has wrong parent."); - } - if (node->right && node->right->parent != node) { - printf("Right child of node has has wrong parent: %p, should be: " - "%p\n", node->right->parent, node); - _DumpNode(node); - debugger("Right child node has wrong parent."); - } - // check heights - int leftHeight = Check(node->left, level + 1); - int rightHeight = Check(node->right, level + 1); - if (node->balance_factor != rightHeight - leftHeight) { - printf("Subtree %p at level %d has wrong balance factor: left " - "height: %d, right height: %d, balance factor: %d\n", - node, level, leftHeight, rightHeight, node->balance_factor); - _DumpNode(node); - debugger("Node has wrong balance factor."); - } - // check AVL property - if (!levelsOnly && (leftHeight - rightHeight > 1 - || leftHeight - rightHeight < -1)) { - printf("Subtree %p at level %d violates the AVL property: left " - "height: %d, right height: %d\n", node, level, leftHeight, - rightHeight); - _DumpNode(node); - debugger("Node violates AVL property."); - } - height = (leftHeight > rightHeight ? leftHeight : rightHeight) + 1; - } - return height; -} - -// _RotateRight -_AVL_TREE_MAP_TEMPLATE_LIST -void -_AVL_TREE_MAP_CLASS_NAME::_RotateRight(Node **nodeP) -{ - // rotate the nodes - Node *node = *nodeP; - Node *left = node->left; -//printf("_RotateRight(): balance: node: %d, left: %d\n", -//node->balance_factor, left->balance_factor); - *nodeP = left; - left->parent = node->parent; - node->left = left->right; - if (left->right) - left->right->parent = node; - left->right = node; - node->parent = left; - // adjust the balance factors - // former pivot - if (left->balance_factor >= 0) - node->balance_factor++; - else - node->balance_factor += 1 - left->balance_factor; - // former left - if (node->balance_factor <= 0) - left->balance_factor++; - else - left->balance_factor += node->balance_factor + 1; -//printf("_RotateRight() end: balance: node: %d, left: %d\n", -//node->balance_factor, left->balance_factor); -} - -// _RotateLeft -_AVL_TREE_MAP_TEMPLATE_LIST -void -_AVL_TREE_MAP_CLASS_NAME::_RotateLeft(Node **nodeP) -{ - // rotate the nodes - Node *node = *nodeP; - Node *right = node->right; -//printf("_RotateLeft(): balance: node: %d, right: %d\n", -//node->balance_factor, right->balance_factor); - *nodeP = right; - right->parent = node->parent; - node->right = right->left; - if (right->left) - right->left->parent = node; - right->left = node; - node->parent = right; - // adjust the balance factors - // former pivot - if (right->balance_factor <= 0) - node->balance_factor--; - else - node->balance_factor -= right->balance_factor + 1; - // former right - if (node->balance_factor >= 0) - right->balance_factor--; - else - right->balance_factor += node->balance_factor - 1; -//printf("_RotateLeft() end: balance: node: %d, right: %d\n", -//node->balance_factor, right->balance_factor); -} - -// _BalanceInsertLeft -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_BalanceInsertLeft(Node **node) -{ -//printf("_BalanceInsertLeft()\n"); -//_DumpNode(*node); -//Check(*node, 0, true); - int result = HEIGHT_CHANGED; - if ((*node)->balance_factor < LEFT) { - // tree is left heavy - Node **left = &(*node)->left; - if ((*left)->balance_factor == LEFT) { - // left left heavy - _RotateRight(node); - } else { - // left right heavy - _RotateLeft(left); - _RotateRight(node); - } - result = OK; - } else if ((*node)->balance_factor == BALANCED) - result = OK; -//printf("_BalanceInsertLeft() done: %d\n", result); - return result; -} - -// _BalanceInsertRight -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_BalanceInsertRight(Node **node) -{ -//printf("_BalanceInsertRight()\n"); -//_DumpNode(*node); -//Check(*node, 0, true); - int result = HEIGHT_CHANGED; - if ((*node)->balance_factor > RIGHT) { - // tree is right heavy - Node **right = &(*node)->right; - if ((*right)->balance_factor == RIGHT) { - // right right heavy - _RotateLeft(node); - } else { - // right left heavy - _RotateRight(right); - _RotateLeft(node); - } - result = OK; - } else if ((*node)->balance_factor == BALANCED) - result = OK; -//printf("_BalanceInsertRight() done: %d\n", result); - return result; -} - -// _Insert -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_Insert(const Key &key, const Value &value, - Node **node, Iterator *iterator) -{ - struct node_info { - Node **node; - bool left; - }; - node_info stack[kMaxAVLTreeHeight]; - node_info *top = stack; - const node_info *const bottom = stack; - // find insertion point - while (*node) { - int cmp = Compare(key, GetKey(*node)); - if (cmp == 0) // duplicate node - return DUPLICATE; - else { - top->node = node; - if (cmp < 0) { - top->left = true; - node = &(*node)->left; - } else { - top->left = false; - node = &(*node)->right; - } - top++; - } - } - // allocate and insert node - *node = Allocate(key, value); - if (*node) { - (*node)->balance_factor = BALANCED; - fNodeCount++; - } else - return NO_MEMORY; - if (top != bottom) - (*node)->parent = *top[-1].node; - // init the iterator - if (iterator) - *iterator = Iterator(this, *node); - // do the balancing - int result = HEIGHT_CHANGED; - while (result == HEIGHT_CHANGED && top != bottom) { - top--; - node = top->node; - if (top->left) { - // left - (*node)->balance_factor--; - result = _BalanceInsertLeft(node); - } else { - // right - (*node)->balance_factor++; - result = _BalanceInsertRight(node); - } - } -//Check(*node); - return result; -} - -// _BalanceRemoveLeft -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_BalanceRemoveLeft(Node **node) -{ -//printf("_BalanceRemoveLeft()\n"); -//_DumpNode(*node); -//Check(*node, 0, true); - int result = HEIGHT_CHANGED; - if ((*node)->balance_factor > RIGHT) { - // tree is right heavy - Node **right = &(*node)->right; - if ((*right)->balance_factor == RIGHT) { - // right right heavy - _RotateLeft(node); - } else if ((*right)->balance_factor == BALANCED) { - // right none heavy - _RotateLeft(node); - result = OK; - } else { - // right left heavy - _RotateRight(right); - _RotateLeft(node); - } - } else if ((*node)->balance_factor == RIGHT) - result = OK; -//printf("_BalanceRemoveLeft() done: %d\n", result); - return result; -} - -// _BalanceRemoveRight -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_BalanceRemoveRight(Node **node) -{ -//printf("_BalanceRemoveRight()\n"); -//_DumpNode(*node); -//Check(*node, 0, true); - int result = HEIGHT_CHANGED; - if ((*node)->balance_factor < LEFT) { - // tree is left heavy - Node **left = &(*node)->left; - if ((*left)->balance_factor == LEFT) { - // left left heavy - _RotateRight(node); - } else if ((*left)->balance_factor == BALANCED) { - // left none heavy - _RotateRight(node); - result = OK; - } else { - // left right heavy - _RotateLeft(left); - _RotateRight(node); - } - } else if ((*node)->balance_factor == LEFT) - result = OK; -//printf("_BalanceRemoveRight() done: %d\n", result); - return result; -} - -// _RemoveRightMostChild -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_RemoveRightMostChild(Node **node, Node **foundNode) -{ - Node **stack[kMaxAVLTreeHeight]; - Node ***top = stack; - const Node *const *const *const bottom = stack; - // find the child - while ((*node)->right) { - *top = node; - top++; - node = &(*node)->right; - } - // found the rightmost child: remove it - // the found node might have a left child: replace the node with the - // child - *foundNode = *node; - Node *left = (*node)->left; - if (left) - left->parent = (*node)->parent; - *node = left; - (*foundNode)->left = NULL; - (*foundNode)->parent = NULL; - // balancing - int result = HEIGHT_CHANGED; - while (result == HEIGHT_CHANGED && top != bottom) { - top--; - node = *top; - (*node)->balance_factor--; - result = _BalanceRemoveRight(node); - } - return result; -} - -// _Remove -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_Remove(const Key &key, Node **node) -{ - struct node_info { - Node **node; - bool left; - }; - node_info stack[kMaxAVLTreeHeight]; - node_info *top = stack; - const node_info *const bottom = stack; - // find node - while (*node) { - int cmp = Compare(key, GetKey(*node)); - if (cmp == 0) - break; - else { - top->node = node; - if (cmp < 0) { - top->left = true; - node = &(*node)->left; - } else { - top->left = false; - node = &(*node)->right; - } - top++; - } - } - if (!*node) - return NOT_FOUND; - // remove and free node - int result = HEIGHT_CHANGED; - Node *oldNode = *node; - Node *replace = NULL; - if ((*node)->left && (*node)->right) { - // node has two children - result = _RemoveRightMostChild(&(*node)->left, &replace); - replace->parent = (*node)->parent; - replace->left = (*node)->left; - replace->right = (*node)->right; - if ((*node)->left) // check necessary, if (*node)->left == replace - (*node)->left->parent = replace; - (*node)->right->parent = replace; - replace->balance_factor = (*node)->balance_factor; - *node = replace; - if (result == HEIGHT_CHANGED) { - replace->balance_factor++; - result = _BalanceRemoveLeft(node); - } - } else if ((*node)->left) { - // node has only left child - replace = (*node)->left; - replace->parent = (*node)->parent; - replace->balance_factor = (*node)->balance_factor + 1; - *node = replace; - } else if ((*node)->right) { - // node has only right child - replace = (*node)->right; - replace->parent = (*node)->parent; - replace->balance_factor = (*node)->balance_factor - 1; - *node = replace; - } else { - // node has no child - *node = NULL; - } - Free(oldNode); - fNodeCount--; - // do the balancing - while (result == HEIGHT_CHANGED && top != bottom) { - top--; - node = top->node; - if (top->left) { - // left - (*node)->balance_factor++; - result = _BalanceRemoveLeft(node); - } else { - // right - (*node)->balance_factor--; - result = _BalanceRemoveRight(node); - } - } -//Check(*node); - return result; -} - -// _Remove -_AVL_TREE_MAP_TEMPLATE_LIST -int -_AVL_TREE_MAP_CLASS_NAME::_Remove(Node *node) +status_t +_AVL_TREE_MAP_CLASS_NAME::Remove(const Key& key) { + AVLTreeNode* node = fTree.Remove(&key); if (!node) - return NOT_FOUND; - // remove and free node - Node *parent = node->parent; - bool isLeft = (parent && parent->left == node); - Node **nodeP - = (parent ? (isLeft ? &parent->left : &parent->right) : &fRoot); - int result = HEIGHT_CHANGED; - Node *replace = NULL; - if (node->left && node->right) { - // node has two children - result = _RemoveRightMostChild(&node->left, &replace); - replace->parent = parent; - replace->left = node->left; - replace->right = node->right; - if (node->left) // check necessary, if node->left == replace - node->left->parent = replace; - node->right->parent = replace; - replace->balance_factor = node->balance_factor; - *nodeP = replace; - if (result == HEIGHT_CHANGED) { - replace->balance_factor++; - result = _BalanceRemoveLeft(nodeP); - } - } else if (node->left) { - // node has only left child - replace = node->left; - replace->parent = parent; - replace->balance_factor = node->balance_factor + 1; - *nodeP = replace; - } else if (node->right) { - // node has only right child - replace = node->right; - replace->parent = node->parent; - replace->balance_factor = node->balance_factor - 1; - *nodeP = replace; - } else { - // node has no child - *nodeP = NULL; - } - Free(node); - fNodeCount--; - // do the balancing - while (result == HEIGHT_CHANGED && parent) { - node = parent; - parent = node->parent; - bool oldIsLeft = isLeft; - isLeft = (parent && parent->left == node); - nodeP = (parent ? (isLeft ? &parent->left : &parent->right) : &fRoot); - if (oldIsLeft) { - // left - node->balance_factor++; - result = _BalanceRemoveLeft(nodeP); - } else { - // right - node->balance_factor--; - result = _BalanceRemoveRight(nodeP); - } - } -//Check(node); - return result; + return B_ENTRY_NOT_FOUND; + + _Free(_GetNode(node)); + return B_OK; } -// _FreeTree + +// CompareKeyNode _AVL_TREE_MAP_TEMPLATE_LIST -void -_AVL_TREE_MAP_CLASS_NAME::_FreeTree(Node *node) +int +_AVL_TREE_MAP_CLASS_NAME::CompareKeyNode(const void* key, + const AVLTreeNode* node) { - if (node) { - _FreeTree(node->left); - _FreeTree(node->right); - fAllocator.Free(node); - } + return _CompareKeyNode(*(const Key*)key, _GetNode(node)); } -// _DumpNode + +// CompareNodes _AVL_TREE_MAP_TEMPLATE_LIST -void -_AVL_TREE_MAP_CLASS_NAME::_DumpNode(Node *node) const +int +_AVL_TREE_MAP_CLASS_NAME::CompareNodes(const AVLTreeNode* node1, + const AVLTreeNode* node2) { - if (!node) - return; - - enum node_type { - ROOT, - LEFT, - RIGHT, - }; - struct node_info { - Node *node; - int id; - int parent; - int level; - int type; - }; - - node_info *queue = new(nothrow) node_info[fNodeCount]; - if (!queue) { - printf("_Dump(): Insufficient memory for allocating queue.\n"); - } - node_info *front = queue; - node_info *back = queue; - back->node = node; - back->id = 0; - back->level = 0; - back->type = ROOT; - back++; - int level = 0; - int nextID = 1; - while (front != back) { - // pop front - node_info *current = front; - front++; - // get to the correct level - node = current->node; - if (level < current->level) { - printf("\n"); - level++; - } - // print node - switch (current->type) { - case ROOT: - printf("[%d:%d]", current->id, node->balance_factor); - break; - case LEFT: - printf("[%d:L:%d:%d]", current->id, current->parent, - node->balance_factor); - break; - case RIGHT: - printf("[%d:R:%d:%d]", current->id, current->parent, - node->balance_factor); - break; - } - // add child nodes - if (node->left) { - back->node = node->left; - back->id = nextID++; - back->parent = current->id; - back->level = current->level + 1; - back->type = LEFT; - back++; - } - if (node->right) { - back->node = node->right; - back->id = nextID++; - back->parent = current->id; - back->level = current->level + 1; - back->type = RIGHT; - back++; - } - } - printf("\n\n"); - delete[] queue; + return _CompareNodes(_GetNode(node1), _GetNode(node2)); } -// Allocate + +// _Allocate _AVL_TREE_MAP_TEMPLATE_LIST -inline -_AVL_TREE_MAP_CLASS_NAME::Node * -_AVL_TREE_MAP_CLASS_NAME::Allocate(const Key &key, const Value &value) +inline _AVL_TREE_MAP_CLASS_NAME::Node* +_AVL_TREE_MAP_CLASS_NAME::_Allocate(const Key& key, const Value& value) { return fStrategy.Allocate(key, value); } -// Free + +// _Free _AVL_TREE_MAP_TEMPLATE_LIST -inline -void -_AVL_TREE_MAP_CLASS_NAME::Free(Node *node) +inline void +_AVL_TREE_MAP_CLASS_NAME::_Free(Node* node) { - return fStrategy.Free(node); + fStrategy.Free(node); } -// GetKey + +// _GetKey _AVL_TREE_MAP_TEMPLATE_LIST -inline -Key & -_AVL_TREE_MAP_CLASS_NAME::GetKey(Node *node) const +inline Key& +_AVL_TREE_MAP_CLASS_NAME::_GetKey(Node* node) const { return fStrategy.GetKey(node); } -// GetValue + +// _GetValue _AVL_TREE_MAP_TEMPLATE_LIST -inline -Value & -_AVL_TREE_MAP_CLASS_NAME::GetValue(Node *node) const +inline Value& +_AVL_TREE_MAP_CLASS_NAME::_GetValue(Node* node) const { return fStrategy.GetValue(node); } -// Compare + +// _GetAVLTreeNode _AVL_TREE_MAP_TEMPLATE_LIST -inline -int -_AVL_TREE_MAP_CLASS_NAME::Compare(const Key &a, const Key &b) +inline AVLTreeNode* +_AVL_TREE_MAP_CLASS_NAME::_GetAVLTreeNode(const Node* node) const { - return fStrategy.Compare(a, b); + return fStrategy.GetAVLTreeNode(const_cast(node)); } -// strategy parameters +// _GetNode +_AVL_TREE_MAP_TEMPLATE_LIST +inline _AVL_TREE_MAP_CLASS_NAME::Node* +_AVL_TREE_MAP_CLASS_NAME::_GetNode(const AVLTreeNode* node) const +{ + return fStrategy.GetNode(const_cast(node)); +} + + +// _CompareKeyNode +_AVL_TREE_MAP_TEMPLATE_LIST +inline int +_AVL_TREE_MAP_CLASS_NAME::_CompareKeyNode(const Key& a, const Node* b) +{ + return fStrategy.CompareKeyNode(a, b); +} + + +// _CompareNodes +_AVL_TREE_MAP_TEMPLATE_LIST +inline int +_AVL_TREE_MAP_CLASS_NAME::_CompareNodes(const Node* a, const Node* b) +{ + return fStrategy.CompareNodes(a, b); +} + + +// _FreeTree +_AVL_TREE_MAP_TEMPLATE_LIST +void +_AVL_TREE_MAP_CLASS_NAME::_FreeTree(AVLTreeNode* node) +{ + if (node) { + _FreeTree(node->left); + _FreeTree(node->right); + _Free(_GetNode(node)); + } +} + + +// #pragma mark - strategy parameters // Ascending namespace AVLTreeMapStrategy { template class Ascending { +public: inline int operator()(const Value &a, const Value &b) const { if (a < b) @@ -1359,10 +680,12 @@ class Ascending { }; } + // Descending namespace AVLTreeMapStrategy { template class Descending { +public: inline int operator()(const Value &a, const Value &b) const { if (a < b) @@ -1374,7 +697,9 @@ class Descending { }; } -// strategies + +// #pragma mark - strategies + // Auto namespace AVLTreeMapStrategy { @@ -1382,54 +707,60 @@ template class Allocator> class Auto { public: - class Node - { - public: + struct Node : AVLTreeNode { Node(const Key &key, const Value &value) - : key(key), - value(value), - parent(NULL), - left(NULL), - right(NULL), - balance_factor(0) + : AVLTreeNode(), + key(key), + value(value) { } Key key; Value value; - Node *parent; - Node *left; - Node *right; - int balance_factor; }; - inline Node *Allocate(const Key &key, const Value &value) + inline Node* Allocate(const Key& key, const Value& value) { - Node *result = fAllocator.Allocate(); + Node* result = fAllocator.Allocate(); if (result) fAllocator.Construct(result, key, value); return result; } - inline void Free(Node *node) + inline void Free(Node* node) { fAllocator.Destruct(node); fAllocator.Deallocate(node); } - inline Key &GetKey(Node *node) const + inline Key& GetKey(Node* node) const { return node->key; } - inline Value &GetValue(Node *node) const + inline Value& GetValue(Node* node) const { return node->value; } - inline int Compare(const Key &a, const Key &b) + inline AVLTreeNode* GetAVLTreeNode(Node* node) const { - return fCompare(a, b); + return node; + } + + inline Node* GetNode(AVLTreeNode* node) const + { + return static_cast(node); + } + + inline int CompareKeyNode(const Key& a, const Node* b) const + { + return fCompare(a, _GetKey(b)); + } + + inline int CompareNodes(const Node* a, const Node* b) const + { + return fCompare(_GetKey(a), _GetKey(b)); } private: diff --git a/headers/private/kernel/util/MallocFreeAllocator.h b/headers/private/kernel/util/MallocFreeAllocator.h index 6489648cc2..5947f4b6fc 100644 --- a/headers/private/kernel/util/MallocFreeAllocator.h +++ b/headers/private/kernel/util/MallocFreeAllocator.h @@ -1,7 +1,7 @@ #ifndef _MALLOC_FREE_ALLOCATOR_H_ #define _MALLOC_FREE_ALLOCATOR_H_ -#include "Constructor.h" +#include #include diff --git a/src/system/kernel/util/AVLTreeMap.cpp b/src/system/kernel/util/AVLTreeMap.cpp new file mode 100644 index 0000000000..e3564cd3e5 --- /dev/null +++ b/src/system/kernel/util/AVLTreeMap.cpp @@ -0,0 +1,565 @@ +/* + * Copyright 2003-2007, Ingo Weinhold . + * Distributed under the terms of the MIT License. + */ + +#include + + +// #pragma mark - AVLTreeCompare + + +AVLTreeCompare::~AVLTreeCompare() +{ +} + + +// #pragma mark - AVLTree + + +AVLTree::AVLTree(AVLTreeCompare* compare) + : fRoot(NULL), + fNodeCount(0), + fCompare(compare) +{ +} + + +AVLTree::~AVLTree() +{ +} + + +void +AVLTree::MakeEmpty() +{ + fRoot = NULL; + fNodeCount = 0; +} + + +status_t +AVLTree::Insert(AVLTreeNode* nodeToInsert) +{ + int result = _Insert(nodeToInsert); + switch (result) { + case OK: + case HEIGHT_CHANGED: + return B_OK; + case NO_MEMORY: + return B_NO_MEMORY; + case DUPLICATE: + default: + return B_BAD_VALUE; + } +} + + +AVLTreeNode* +AVLTree::Remove(const void* key) +{ + // find node + AVLTreeNode* node = fRoot; + while (node) { + int cmp = fCompare->CompareKeyNode(key, node); + if (cmp == 0) + break; + else { + if (cmp < 0) + node = node->left; + else + node = node->right; + } + } + + // remove it + if (node) + _Remove(node); + + return node; +} + + +bool +AVLTree::Remove(AVLTreeNode* node) +{ + switch (_Remove(node)) { + case OK: + case HEIGHT_CHANGED: + return true; + case NOT_FOUND: + default: + return false; + } +} + + +AVLTreeNode* +AVLTree::LeftMost(AVLTreeNode* node) const +{ + if (node) { + while (node->left) + node = node->left; + } + + return node; +} + + +AVLTreeNode* +AVLTree::RightMost(AVLTreeNode* node) const +{ + if (node) { + while (node->right) + node = node->right; + } + + return node; +} + + +AVLTreeNode* +AVLTree::Previous(AVLTreeNode* node) const +{ + if (node) { + // The previous node cannot be in the right subtree. + if (node->left) { + // We have a left subtree, so go to the right-most node. + node = node->left; + while (node->right) + node = node->right; + } else { + // No left subtree: Backtrack our path and stop, where we + // took the right branch. + AVLTreeNode* previous; + do { + previous = node; + node = node->parent; + } while (node && previous == node->left); + } + } + + return node; +} + + +AVLTreeNode* +AVLTree::Next(AVLTreeNode* node) const +{ + if (node) { + // The next node cannot be in the left subtree. + if (node->right) { + // We have a right subtree, so go to the left-most node. + node = node->right; + while (node->left) + node = node->left; + } else { + // No right subtree: Backtrack our path and stop, where we + // took the left branch. + AVLTreeNode* previous; + do { + previous = node; + node = node->parent; + } while (node && previous == node->right); + } + } + + return node; +} + + +AVLTreeNode* +AVLTree::Find(const void* key) +{ + AVLTreeNode* node = fRoot; + + while (node) { + int cmp = fCompare->CompareKeyNode(key, node); + if (cmp == 0) + return node; + + if (cmp < 0) + node = node->left; + else + node = node->right; + } + + return NULL; +} + + +AVLTreeNode* +AVLTree::FindClose(const void* key, bool less) +{ + AVLTreeNode* node = fRoot; + AVLTreeNode* parent = NULL; + + while (node) { + int cmp = fCompare->CompareKeyNode(key, node); + if (cmp == 0) + break; + + parent = node; + if (cmp < 0) + node = node->left; + else + node = node->right; + } + + // not found: try to get close + if (!node && parent) { + node = parent; + int expectedCmp = (less ? 1 : -1); + int cmp = fCompare->CompareKeyNode(key, node); + if (cmp != expectedCmp) { + // The node's value is less although we were asked for a greater + // value, or the other way around. We need to iterate to the next + // node in the respective direction. If there is no node, we fail. + if (less) + return Previous(node); + return Next(node); + } + } + + return node; +} + + +void +AVLTree::_RotateRight(AVLTreeNode** nodeP) +{ + // rotate the nodes + AVLTreeNode* node = *nodeP; + AVLTreeNode* left = node->left; + + *nodeP = left; + + left->parent = node->parent; + node->left = left->right; + if (left->right) + left->right->parent = node; + left->right = node; + node->parent = left; + + // adjust the balance factors + // former pivot + if (left->balance_factor >= 0) + node->balance_factor++; + else + node->balance_factor += 1 - left->balance_factor; + + // former left + if (node->balance_factor <= 0) + left->balance_factor++; + else + left->balance_factor += node->balance_factor + 1; +} + + +void +AVLTree::_RotateLeft(AVLTreeNode** nodeP) +{ + // rotate the nodes + AVLTreeNode* node = *nodeP; + AVLTreeNode* right = node->right; + + *nodeP = right; + + right->parent = node->parent; + node->right = right->left; + if (right->left) + right->left->parent = node; + right->left = node; + node->parent = right; + + // adjust the balance factors + // former pivot + if (right->balance_factor <= 0) + node->balance_factor--; + else + node->balance_factor -= right->balance_factor + 1; + + // former right + if (node->balance_factor >= 0) + right->balance_factor--; + else + right->balance_factor += node->balance_factor - 1; +} + + +int +AVLTree::_BalanceInsertLeft(AVLTreeNode** node) +{ + if ((*node)->balance_factor < LEFT) { + // tree is left heavy + AVLTreeNode** left = &(*node)->left; + if ((*left)->balance_factor == LEFT) { + // left left heavy + _RotateRight(node); + } else { + // left right heavy + _RotateLeft(left); + _RotateRight(node); + } + return OK; + } + + if ((*node)->balance_factor == BALANCED) + return OK; + + return HEIGHT_CHANGED; +} + + +int +AVLTree::_BalanceInsertRight(AVLTreeNode** node) +{ + if ((*node)->balance_factor > RIGHT) { + // tree is right heavy + AVLTreeNode** right = &(*node)->right; + if ((*right)->balance_factor == RIGHT) { + // right right heavy + _RotateLeft(node); + } else { + // right left heavy + _RotateRight(right); + _RotateLeft(node); + } + return OK; + } + + if ((*node)->balance_factor == BALANCED) + return OK; + + return HEIGHT_CHANGED; +} + + +int +AVLTree::_Insert(AVLTreeNode* nodeToInsert) +{ + struct node_info { + AVLTreeNode** node; + bool left; + }; + + node_info stack[kMaxAVLTreeHeight]; + node_info* top = stack; + const node_info* const bottom = stack; + AVLTreeNode** node = &fRoot; + + // find insertion point + while (*node) { + int cmp = fCompare->CompareNodes(nodeToInsert, *node); + if (cmp == 0) // duplicate node + return DUPLICATE; + else { + top->node = node; + if (cmp < 0) { + top->left = true; + node = &(*node)->left; + } else { + top->left = false; + node = &(*node)->right; + } + top++; + } + } + + // insert node + *node = nodeToInsert; + nodeToInsert->left = NULL; + nodeToInsert->right = NULL; + nodeToInsert->balance_factor = BALANCED; + fNodeCount++; + + if (top == bottom) + nodeToInsert->parent = NULL; + else + (*node)->parent = *top[-1].node; + + // init the iterator +// if (iterator) +// *iterator = Iterator(this, *node); + + // do the balancing + int result = HEIGHT_CHANGED; + while (result == HEIGHT_CHANGED && top != bottom) { + top--; + node = top->node; + if (top->left) { + // left + (*node)->balance_factor--; + result = _BalanceInsertLeft(node); + } else { + // right + (*node)->balance_factor++; + result = _BalanceInsertRight(node); + } + } + + return result; +} + + +int +AVLTree::_BalanceRemoveLeft(AVLTreeNode** node) +{ + int result = HEIGHT_CHANGED; + + if ((*node)->balance_factor > RIGHT) { + // tree is right heavy + AVLTreeNode** right = &(*node)->right; + if ((*right)->balance_factor == RIGHT) { + // right right heavy + _RotateLeft(node); + } else if ((*right)->balance_factor == BALANCED) { + // right none heavy + _RotateLeft(node); + result = OK; + } else { + // right left heavy + _RotateRight(right); + _RotateLeft(node); + } + } else if ((*node)->balance_factor == RIGHT) + result = OK; + + return result; +} + + +int +AVLTree::_BalanceRemoveRight(AVLTreeNode** node) +{ + int result = HEIGHT_CHANGED; + + if ((*node)->balance_factor < LEFT) { + // tree is left heavy + AVLTreeNode** left = &(*node)->left; + if ((*left)->balance_factor == LEFT) { + // left left heavy + _RotateRight(node); + } else if ((*left)->balance_factor == BALANCED) { + // left none heavy + _RotateRight(node); + result = OK; + } else { + // left right heavy + _RotateLeft(left); + _RotateRight(node); + } + } else if ((*node)->balance_factor == LEFT) + result = OK; + + return result; +} + + +int +AVLTree::_RemoveRightMostChild(AVLTreeNode** node, AVLTreeNode** foundNode) +{ + AVLTreeNode** stack[kMaxAVLTreeHeight]; + AVLTreeNode*** top = stack; + const AVLTreeNode* const* const* const bottom = stack; + + // find the child + while ((*node)->right) { + *top = node; + top++; + node = &(*node)->right; + } + + // found the rightmost child: remove it + // the found node might have a left child: replace the node with the + // child + *foundNode = *node; + AVLTreeNode* left = (*node)->left; + if (left) + left->parent = (*node)->parent; + *node = left; + (*foundNode)->left = NULL; + (*foundNode)->parent = NULL; + + // balancing + int result = HEIGHT_CHANGED; + while (result == HEIGHT_CHANGED && top != bottom) { + top--; + node = *top; + (*node)->balance_factor--; + result = _BalanceRemoveRight(node); + } + + return result; +} + + +int +AVLTree::_Remove(AVLTreeNode* node) +{ + if (!node) + return NOT_FOUND; + + // remove node + AVLTreeNode* parent = node->parent; + bool isLeft = (parent && parent->left == node); + AVLTreeNode** nodeP + = (parent ? (isLeft ? &parent->left : &parent->right) : &fRoot); + int result = HEIGHT_CHANGED; + AVLTreeNode* replace = NULL; + + if (node->left && node->right) { + // node has two children + result = _RemoveRightMostChild(&node->left, &replace); + replace->parent = parent; + replace->left = node->left; + replace->right = node->right; + if (node->left) // check necessary, if node->left == replace + node->left->parent = replace; + node->right->parent = replace; + replace->balance_factor = node->balance_factor; + *nodeP = replace; + + if (result == HEIGHT_CHANGED) { + replace->balance_factor++; + result = _BalanceRemoveLeft(nodeP); + } + } else if (node->left) { + // node has only left child + replace = node->left; + replace->parent = parent; + replace->balance_factor = node->balance_factor + 1; + *nodeP = replace; + } else if (node->right) { + // node has only right child + replace = node->right; + replace->parent = node->parent; + replace->balance_factor = node->balance_factor - 1; + *nodeP = replace; + } else { + // node has no child + *nodeP = NULL; + } + + fNodeCount--; + + // do the balancing + while (result == HEIGHT_CHANGED && parent) { + node = parent; + parent = node->parent; + bool oldIsLeft = isLeft; + isLeft = (parent && parent->left == node); + nodeP = (parent ? (isLeft ? &parent->left : &parent->right) : &fRoot); + if (oldIsLeft) { + // left + node->balance_factor++; + result = _BalanceRemoveLeft(nodeP); + } else { + // right + node->balance_factor--; + result = _BalanceRemoveRight(nodeP); + } + } + + return result; +} diff --git a/src/system/kernel/util/Jamfile b/src/system/kernel/util/Jamfile index b62ff5724d..b906307220 100644 --- a/src/system/kernel/util/Jamfile +++ b/src/system/kernel/util/Jamfile @@ -3,6 +3,7 @@ SubDir HAIKU_TOP src system kernel util ; UsePrivateHeaders [ FDirName kernel util ] ; KernelMergeObject kernel_util.o : + AVLTreeMap.cpp cbuf.c kernel_cpp.cpp khash.c