// 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. #ifndef _AVL_TREE_MAP_H #define _AVL_TREE_MAP_H #include #include #include "MallocFreeAllocator.h" // maximal height of a tree static const int kMaxAVLTreeHeight = 32; // strategies namespace AVLTreeMapStrategy { // key orders template class Ascending; template class Descending; //! Automatic node strategy (works like STL containers do) template , 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; // }; } template class AVLTreeMapIterator; template class AVLTreeMapEntry; template class AVLTreeMapEntryPointer; // for convenience #define _AVL_TREE_MAP_TEMPLATE_LIST template #define _AVL_TREE_MAP_CLASS_NAME AVLTreeMap // AVLTreeMap template > class AVLTreeMap { 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(); inline int Count() const { return fNodeCount; } inline bool IsEmpty() const { return (fNodeCount == 0); } 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); } 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); Iterator Erase(const Iterator &iterator); // debugging int Check(Node *node = NULL, int level = 0, bool levelsOnly = false) const; protected: enum { NOT_FOUND = -3, DUPLICATE = -2, NO_MEMORY = -1, OK = 0, HEIGHT_CHANGED = 1, 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; // 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); protected: friend class Entry; friend class Iterator; friend class ConstIterator; friend AVLTreeMapIterator; friend AVLTreeMapIterator; Node *fRoot; int fNodeCount; NodeStrategy fStrategy; // Iterator class Iterator : public AVLTreeMapIterator<_AVL_TREE_MAP_CLASS_NAME> { private: typedef AVLTreeMapIterator<_AVL_TREE_MAP_CLASS_NAME> SuperClass; 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); 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); 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() { } _AVL_TREE_MAP_TEMPLATE_LIST inline _AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator( const ConstIterator &other) : SuperClass(other) { } _AVL_TREE_MAP_TEMPLATE_LIST inline _AVL_TREE_MAP_CLASS_NAME::ConstIterator::ConstIterator(const Iterator &other) : SuperClass(other.fParent, other.fCurrent) { } _AVL_TREE_MAP_TEMPLATE_LIST inline _AVL_TREE_MAP_CLASS_NAME::ConstIterator & _AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator++() { SuperClass::operator++(); return *this; } _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; } _AVL_TREE_MAP_TEMPLATE_LIST inline _AVL_TREE_MAP_CLASS_NAME::ConstIterator & _AVL_TREE_MAP_CLASS_NAME::ConstIterator::operator--() { SuperClass::operator--(); return *this; } _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; } _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; } _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; } _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) { } // AVLTreeMap // constructor _AVL_TREE_MAP_TEMPLATE_LIST _AVL_TREE_MAP_CLASS_NAME::AVLTreeMap() : fRoot(NULL), fNodeCount(0) { } // destructor _AVL_TREE_MAP_TEMPLATE_LIST _AVL_TREE_MAP_CLASS_NAME::~AVLTreeMap() { _FreeTree(fRoot); fRoot = NULL; } // MakeEmpty _AVL_TREE_MAP_TEMPLATE_LIST void _AVL_TREE_MAP_CLASS_NAME::MakeEmpty() { _FreeTree(fRoot); fRoot = NULL; fNodeCount = 0; } // Find _AVL_TREE_MAP_TEMPLATE_LIST _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(); } // FindClose _AVL_TREE_MAP_TEMPLATE_LIST _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); } // Insert _AVL_TREE_MAP_TEMPLATE_LIST status_t _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; } } // 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) { 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; } // _FreeTree _AVL_TREE_MAP_TEMPLATE_LIST void _AVL_TREE_MAP_CLASS_NAME::_FreeTree(Node *node) { if (node) { _FreeTree(node->left); _FreeTree(node->right); fAllocator.Free(node); } } // _DumpNode _AVL_TREE_MAP_TEMPLATE_LIST void _AVL_TREE_MAP_CLASS_NAME::_DumpNode(Node *node) const { 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; } // 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) { return fStrategy.Allocate(key, value); } // Free _AVL_TREE_MAP_TEMPLATE_LIST inline void _AVL_TREE_MAP_CLASS_NAME::Free(Node *node) { return fStrategy.Free(node); } // GetKey _AVL_TREE_MAP_TEMPLATE_LIST inline Key & _AVL_TREE_MAP_CLASS_NAME::GetKey(Node *node) const { return fStrategy.GetKey(node); } // GetValue _AVL_TREE_MAP_TEMPLATE_LIST inline Value & _AVL_TREE_MAP_CLASS_NAME::GetValue(Node *node) const { return fStrategy.GetValue(node); } // Compare _AVL_TREE_MAP_TEMPLATE_LIST inline int _AVL_TREE_MAP_CLASS_NAME::Compare(const Key &a, const Key &b) { return fStrategy.Compare(a, b); } // strategy parameters // Ascending namespace AVLTreeMapStrategy { template class Ascending { inline int operator()(const Value &a, const Value &b) const { if (a < b) return -1; else if (a > b) return 1; return 0; } }; } // Descending namespace AVLTreeMapStrategy { template class Descending { inline int operator()(const Value &a, const Value &b) const { if (a < b) return -1; else if (a > b) return 1; return 0; } }; } // strategies // Auto namespace AVLTreeMapStrategy { template class Allocator> class Auto { public: class Node { public: Node(const Key &key, const Value &value) : key(key), value(value), parent(NULL), left(NULL), right(NULL), balance_factor(0) { } Key key; Value value; Node *parent; Node *left; Node *right; int balance_factor; }; inline Node *Allocate(const Key &key, const Value &value) { Node *result = fAllocator.Allocate(); if (result) fAllocator.Construct(result, key, value); return result; } inline void Free(Node *node) { fAllocator.Destruct(node); fAllocator.Deallocate(node); } inline Key &GetKey(Node *node) const { return node->key; } inline Value &GetValue(Node *node) const { return node->value; } inline int Compare(const Key &a, const Key &b) { return fCompare(a, b); } private: KeyOrder fCompare; Allocator fAllocator; }; } #endif // _AVL_TREE_MAP_H