haiku/headers/private/kernel/util/AVLTreeMap.h
Axel Dörfler 960371b741 Replaced <new> with <util/kernel_cpp.h> - this is the kernel.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7913 a95241bf-73f2-0310-859d-f6bbb57e9c96
2004-06-11 21:00:10 +00:00

1442 lines
32 KiB
C++

// 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 <OS.h>
#include <util/kernel_cpp.h>
#include "MallocFreeAllocator.h"
// maximal height of a tree
static const int kMaxAVLTreeHeight = 32;
// strategies
namespace AVLTreeMapStrategy {
// key orders
template<typename Value> class Ascending;
template<typename Value> class Descending;
//! Automatic node strategy (works like STL containers do)
template <typename Key, typename Value,
typename KeyOrder = Ascending<Key>,
template <typename> class Allocator = MallocFreeAllocator>
class Auto;
//! User managed node strategy (user is responsible for node allocation/deallocation)
// template <class Node, Node* Node::* NextMember = &Node::next>
// class User;
// NodeStrategy::Node must implement this interface.
// struct Node {
// Node *parent;
// Node *left;
// Node *right;
// int balance_factor;
// };
}
template<typename Parent> class AVLTreeMapIterator;
template<typename Parent> class AVLTreeMapEntry;
template<typename Parent> class AVLTreeMapEntryPointer;
// for convenience
#define _AVL_TREE_MAP_TEMPLATE_LIST template<typename Key, typename Value, \
typename NodeStrategy>
#define _AVL_TREE_MAP_CLASS_NAME AVLTreeMap<Key, Value, NodeStrategy>
// AVLTreeMap
template<typename Key, typename Value,
typename NodeStrategy = AVLTreeMapStrategy::Auto<Key, Value> >
class AVLTreeMap {
private:
typedef typename NodeStrategy::Node Node;
typedef _AVL_TREE_MAP_CLASS_NAME Class;
typedef AVLTreeMapEntry<Class> 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<Class>;
friend AVLTreeMapIterator<const Class>;
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<const _AVL_TREE_MAP_CLASS_NAME> {
private:
typedef AVLTreeMapIterator<const _AVL_TREE_MAP_CLASS_NAME> 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<typename Parent>
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<Parent>;
friend class AVLTreeMapIterator<Parent>;
friend class AVLTreeMapIterator<const Parent>;
const Parent *fParent;
Parent::Node *fNode;
};
// AVLTreeMapEntryPointer
template<typename Parent>
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<Parent>;
friend class AVLTreeMapIterator<const Parent>;
AVLTreeMapEntry<Parent> fEntry;
};
// AVLTreeMapIterator
template<typename Parent>
class AVLTreeMapIterator {
private:
typedef AVLTreeMapIterator<Value, Parent> Iterator;
typedef typename Parent::Node Node;
typedef typename Parent::Entry Entry;
typedef AVLTreeMapEntryPointer<Parent::Class> 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<typename Value>
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<typename Value>
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 <typename Key, typename Value, typename KeyOrder,
template <typename> 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<Node> fAllocator;
};
}
#endif // _AVL_TREE_MAP_H