960371b741
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7913 a95241bf-73f2-0310-859d-f6bbb57e9c96
1442 lines
32 KiB
C++
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
|