Click here to Skip to main content
15,891,136 members
Articles / Programming Languages / C++

STL containers map, set, and list with fast array access

Rate me:
Please Sign up or sign in to vote.
3.71/5 (4 votes)
5 Aug 2002CPOL 205.9K   1.4K   37  
Source code for STL compliant container classes that add fast indexing capability to existing container types
//*************************************************************************************
//	Copyright 2001 by Raymond A. Virzi, Jr.
//	You may freely use and distribute this source code provide the above copyright notice
//	and this statement remains intact within the source module or any modified versions of it.
//	email:	mail@rvirzi.com
//
// The class AVLTree<T> was originally created by Andreas Jager.
// It has been modified a bit but the essential algorithms and
// basic functionality has remained intact. I added logic to keep
// track of the indexes allowing the derived classes to work.
//
// Here is the original copyright notice:
//*************************************************************
// Creator: Andreas J�ger
//          Ortsstr. Nr. 2
//        D-07407 Geitersdorf
//
// Last updated: 15. November 1998
// e-mail: Jaeger-Geitersdorf@t-online.de
//
// 
// Copyright and author: 
// Andreas J�ger: Jaeger-Geitersdorf@t-online.de
// 
// You may handle this code to others only when you do not delete these
// copyright-lines.
// These source files may not be copied except by permission of the author.
// These source files may not be included in source or compiled form as any
// part of a commercial distribution except by permission of the
// author. 
// These files may be used freely for internal corporate use.
// These files may also may be used freely by students for 
// educational purposes.
// No warranty or guarrantee of fitness can be made to these files.
//
// 
// have fun!
//
// Updates:
// 
// * 15.11.1998 - Some fixes in Delete()- and RestructureDelete()-
//                routines which could make the tree inconsistent
//                and result in a GPF (after lots of Insert- and 
//                Delete-operations)
//              - Rename Level() -> GetLevel()
//              - new methods GetDepth() and GetCount() for 
//                AVLTree class
//              - new (debug) function CheckBalances()
//              - Draw() function only in Visual C++ environment
//                (not Borland) for portability
//              - updated sample project
//***************************************************************
//////////////////////////////////////////////////////////////////
// Introduction:
//
// Five STL containers are derived from an AVL tree. These are index_list,
// index_set, index_multiset, index_map, index_multimap, all of which 
// are explained at the beginning of each class definition. The unique
// feature of the classes is that they include a fast indexing operation
// (operator[]) made possible by adding an extra long int for each
// tree node to hold the total number of child nodes below it. The extra
// logic required to update these counters does not add to the complexity
// of any of the tree's original algorithms.
// NOTE: The STL interfaces may not be fully complete.
//--------------------------------------------------------------------
// Change History:
// 03/06/01 - Added this copyright notice and uploaded to Code Project
// 03/08/01 - Copy constructor for Sorted_AVLTree was not working -
//            same for sorted containers.
//          - Sortred_AVLTree::swap() missed a data member.
//			- Constructor for index_list which takes a sequence did not
//            preserve the sequence order.
//          - Added assignment operators to all classes via the base classes.
//          - Added empty virtual destructors to all STL classes.
// 11/27/01	- Fixed bugs in random access iterator functions (operator+=,operator-=)
//			  These were not working all the time for n > 1.
//			- Reworked base classes in iterator_base.h to work better with STL template functions.
// 07/20/02	- Fixed return value error in compilation of index_multiset insert function.
//			- Fixed access errors in compilation of index_multiset do to erroneous non-public derivation.
// 08/04/02	- Count function was not working when limit reached the end of container. This caused 
//			  erroneous results for count() function in all associative classes (sets and maps).

#ifndef __AVLTREE_H
#define __AVLTREE_H

// disable STL warnings
#pragma warning(disable:4786)	// truncated identifier in the browser
#pragma warning(disable:4503)	// truncated decorated name

#include <memory>
#include <utility>
#include <functional>
#include <algorithm>
#include <assert.h>

#include "iterator_base.h"

// Forward declarations
template<class T> class AVLNode;
template<class T> class AVLTree;

//--------------------------------------------------------------
// class AVLNode

template<class T>
class AVLNode
{
	friend class AVLTree<T>;

	// standard constructor, constructors, destructor
	AVLNode(const T& data, AVLNode<T>* parent = NULL, AVLNode<T>* left = NULL, AVLNode<T>* right = NULL);
	~AVLNode();
public:
	T Data;		// item data
	AVLNode<T>* Parent;	// parent node
	AVLNode<T>* Left;		// left subtree
	AVLNode<T>* Right;		// right subtree
	unsigned long _count;	// number of nodes in tree, including this.
	int Balance;
		// information about the height of the subtrees
		// -1: left subtree is 1 higher than the right one
		//  0: both subtrees have the same height
		//  1: right subtree is 1 higher than the left one

	// restructuration
	bool LeftRotation();
	bool RightRotation();
	bool DoubleRotationLeft();
	bool DoubleRotationRight();
	bool RestructureInsert();
	bool RestructureDelete();
public:
	// Access to data
	T& GetData() { return Data;}
	const T& GetData() const { return Data;}
	// information about the position in the tree
	bool IsRoot() const;
	bool IsLeftSibling() const;
	bool IsRightSibling() const;
	bool HasLeftSibling() const;
	bool HasRightSibling() const;
	// further information
	int GetDepth() const;
	int GetLevel() const;
	unsigned long GetCount() const { return _count;}
	unsigned long GetIndex() const;
	unsigned long GetPositionInTree() const { return Left ? Left->_count : 0;}
	// retrieving other nodes
	AVLNode<T>* GetRoot();
	AVLNode<T>* GetLeftSibling();
	AVLNode<T>* GetRightSibling();
	AVLNode<T>* GetNodeInTree(unsigned long n);
	AVLNode<T>* GetFirstNodeInTree();
	AVLNode<T>* GetLastNodeInTree();
	AVLNode<T>* GetPrevNodeInOrder(unsigned long n = 1);
	AVLNode<T>* GetNextNodeInOrder(unsigned long n = 1);
	// diagnostics
	bool Validate() const;
};


template<class T>
AVLNode<T>::AVLNode(const T& data, AVLNode<T>* parent, AVLNode<T>* left, AVLNode<T>* right)
	: Data(data), Parent(parent), Left(left), Right(right)
{
	// Calculate balance
	Balance = 0;
	Balance += Right ? Right->GetDepth() : 0;
	Balance -= Left ? Left->GetDepth() : 0;

	// Calculate count
	_count = 1;			// add one for this node
	_count += Left ? Left->GetCount() : 0;
	_count += Right ? Right->GetCount() : 0;
}

template <class T>
AVLNode<T>::~AVLNode()
{
	if(Left)
		delete Left;
	if(Right)
		delete Right;
}

template <class T>
bool AVLNode<T>::RestructureInsert()
{
	AVLNode<T>* item = this;
	while(!item->IsRoot())
	{
		switch(item->Parent->Balance)
		{
		case 0:
			if(item->IsLeftSibling())
			{
				item->Parent->Balance = -1;
				item = item->Parent;
			}
			else
			{
				item->Parent->Balance = 1;
				item = item->Parent;
			}
			continue;
		case 1:
			if(item->IsLeftSibling())
			{
				item->Parent->Balance = 0;
			}
			else
			{
				if (item->Balance == -1)
					item->Parent->DoubleRotationRight();
				else
					item->Parent->LeftRotation();
			}
			return true;
		case -1:
			if(item->IsLeftSibling())
			{
				if (item->Balance == 1)
					item->Parent->DoubleRotationLeft();
				else
					item->Parent->RightRotation();
			}
			else
			{
				item->Parent->Balance = 0;
			}
			return true;
		}
		assert(false);		// should never reach
	}
	return true;
}

template <class T>
bool AVLNode<T>::RestructureDelete()
{
	AVLNode<T>* item = this;
	switch(item->Balance)
	{
	case 0:
		if(item->Left == NULL) 
		{
			item->Balance = 1;
			return true;
		}
		if(item->Right == NULL) 
		{
			item->Balance = -1;
			return true;
		}
		break;
	case 1:
		if(item->Right == NULL)
		{
			item->Balance = 0;
		}
		else if(item->Left == NULL)
		{
			if(item->Right->Balance == -1)
			{
				item->DoubleRotationRight();
				item = item->Parent;
			}
			else
			{
				item->LeftRotation();
				item = item->Parent;
			}
			if(item->Balance == -1)
				return true;
		}
		break;
	case -1:
		if(item->Left == NULL)
		{
			item->Balance = 0;
		}
		else if(item->Right == NULL)
		{
			if(item->Left->Balance == 1)
			{
				item->DoubleRotationLeft();
				item = item->Parent;
			}
			else
			{
				item->RightRotation();
				item = item->Parent;
			}
			if(item->Balance == 1)
				return true;
		}
		break;
	}

	while(!item->IsRoot())
	{
		switch(item->Parent->Balance)
		{
		case 0:
			if(item->IsLeftSibling())
			{
				item->Parent->Balance = 1;
			}
			else
			{
				item->Parent->Balance = -1;
			}
			return true;
		case -1:
			if(item->IsLeftSibling())
			{
				item->Parent->Balance = 0;
				item = item->Parent;
			}
			else
			{
				if(item->Parent->Left->Balance == 1)
				{
					item->Parent->DoubleRotationLeft();
					item = item->Parent->Parent;
				}
				else
				{
					item->Parent->RightRotation();
					item = item->Parent->Parent;
				}
				if(item->Balance == 1)
					return true;
			}
			continue;
		case 1:
			if(item->IsRightSibling())
			{
				item->Parent->Balance = 0;
				item = item->Parent;
			}
			else
			{
				if(item->Parent->Right->Balance == -1)
				{
					item->Parent->DoubleRotationRight();
					item = item->Parent->Parent;
				}
				else
				{
					item->Parent->LeftRotation();
					item = item->Parent->Parent;
				}
				if(item->Balance == -1)
					return true;
			}
			continue;
		}
		assert(false);		// should never reach
	}
	return true;
}

template <class T>
bool AVLNode<T>::IsRoot() const
{
	return Parent == NULL;
}

template <class T>
bool AVLNode<T>::IsLeftSibling() const
{
	return !IsRoot() && Parent->Left == this;
}

template <class T>
bool AVLNode<T>::IsRightSibling() const
{
	return !IsRoot() && Parent->Right == this;
}

template <class T>
bool AVLNode<T>::HasLeftSibling() const
{
	return IsRightSibling() && Parent->Left != NULL;
}
	
template <class T>
bool AVLNode<T>::HasRightSibling() const
{
	return IsLeftSibling() && Parent->Right != NULL;
}

template <class T>
int AVLNode<T>::GetDepth() const
{
	int i = 0, j;
	if (Left != NULL)
		i = Left->GetDepth();
	if (Right != NULL)
	{
		j = Right->GetDepth();
		if(j > i)
			i = j;
	}
	return i+1;
}

template <class T>
int AVLNode<T>::GetLevel() const
{
	const AVLNode<T>* item = this;
	int level = 0;
	while (item->Parent != NULL)
	{
		item = item->Parent;
		level++;
	}
	return level;
}

template <class T>
AVLNode<T>* AVLNode<T>::GetRoot()
{
	AVLNode<T>* item = this;
	while (item->Parent != NULL) 
		item = item->Parent;
	return item;
}

template <class T>
AVLNode<T>* AVLNode<T>::GetLeftSibling()
{
	if (IsRoot() || IsLeftSibling()) 
		return NULL;
	return Parent->Left;
}

template <class T>
AVLNode<T>* AVLNode<T>::GetRightSibling()
{
	if (IsRoot() || IsRightSibling()) 
		return NULL;
	return Parent->Right;
}

template <class T>
AVLNode<T>* AVLNode<T>::GetFirstNodeInTree()
{
	AVLNode<T>* item = this;
	while(item->Left != NULL)
	{
		item = item->Left;
	}
	return item;
}

template <class T>
AVLNode<T>* AVLNode<T>::GetLastNodeInTree()
{
	AVLNode<T>* item = this;
	while(item->Right != NULL)
	{
		item = item->Right;
	}
	return item;
}

template <class T>
AVLNode<T>* AVLNode<T>::GetPrevNodeInOrder(unsigned long n)
// Gets the node which is 'n' before this one. Returns NULL if 'n' is out of range.
{
	if(n == 0)
		return this;
	if(Left)
	{
		if(n <= Left->_count)
			return Left->GetNodeInTree(Left->_count-n);
		else
			n -= Left->_count;
	}
	AVLNode<T>* item = this;
	while(item->IsLeftSibling())
	{
		item = item->Parent;
	}
	item = item->Parent;
	if(!item)
		return NULL;
	return item->GetPrevNodeInOrder(n-1);
}

template <class T>
AVLNode<T>* AVLNode<T>::GetNextNodeInOrder(unsigned long n)
// Gets the node which is 'n' after this one. Returns NULL if 'n' is out of range.
{
	if(n == 0)
		return this;
	if(Right)
	{
		if(n <= Right->_count)
			return Right->GetNodeInTree(n-1);
		else
			n -= Right->_count;
	}
	AVLNode<T>* item = this;
	while(item->IsRightSibling())
	{
		item = item->Parent;
	}
	item = item->Parent;
	if(!item)
		return NULL;
	return item->GetNextNodeInOrder(n-1);
}

template<class T>
AVLNode<T>* AVLNode<T>::GetNodeInTree(unsigned long n)
// Returns the 'n'th(0-based) node in the subtree. Returns NULL if 'n' is 
// out of range.
{
unsigned long cnt;

	cnt = Left ? Left->_count : 0;
	if(n == cnt)
		return this;
	if(n < cnt)
	{
		return Left->GetNodeInTree(n);
	}
	n -= (cnt+1);
	cnt = Right ? Right->_count : 0;
	if(n >= cnt)		// out of range
		return NULL;
	return Right->GetNodeInTree(n);
}

template<class T>
unsigned long AVLNode<T>::GetIndex() const
// Returns the 0-based index of this node in the entire tree.
// Not valid for end marker!
{
unsigned long n;

	n = GetPositionInTree();
	const AVLNode<T>* item = this;
	while(item->IsLeftSibling())
	{
		item = item->Parent;
	}
	item = item->Parent;
	if(!item)
		return n;
	n++;		// add one for the parent item itself
	n += item->GetIndex();
	return n;
}

template <class T>
bool AVLNode<T>::LeftRotation()
{
	assert(Right);
	
	AVLNode<T>* b = Right;
	if(!IsRoot())
	{
		if(IsLeftSibling())
			Parent->Left = b;
		else
			Parent->Right = b;
		b->Parent = Parent;
	}
	else
	{
		b->Parent = NULL;
	}
	
	// Update counters
	b->_count++;
	b->_count += (Left ? Left->_count : 0);
	_count--;
	assert(b->Right);
	_count -= b->Right->_count;

	// Do the switch
	Right = b->Left;
	b->Left = this;

	// Re-align parents
	Parent = b;
	if(Right)
		Right->Parent = this;

	// Assume Balance == 2 before rotation is called
	// Assume b->Balance != -1 because that calls for double rotation
	if(b->Balance == 0)
	{
		Balance = 1;
		b->Balance = -1;
	}
	else	// b->Balance == 1
	{
		Balance = 0;
		b->Balance = 0;
	}

	return true;
}

template <class T>
bool AVLNode<T>::RightRotation()
{
	assert(Left);
	
	AVLNode<T>* b = Left;
	if(!IsRoot())
	{
		if(IsLeftSibling())
			Parent->Left = b;
		else
			Parent->Right = b;
		b->Parent = Parent;
	}
	else
	{
		b->Parent = NULL;
	}
	
	// Update counters
	b->_count++;
	b->_count += (Right ? Right->_count : 0);
	_count--;
	assert(b->Left);
	_count -= b->Left->_count;

	// Do the switch
	Left = b->Right;
	b->Right = this;

	// Re-align parents
	Parent = b;
	if(Left != NULL) 
		Left->Parent = this;

	// Assume Balance == -2 before rotation is called
	// Assume b->Balance != 1 because that calls for double rotation
	if(b->Balance == 0)
	{
		Balance = -1;
		b->Balance = 1;
	}
	else		// b->Balance == -1
	{
		Balance = 0;
		b->Balance = 0;
	}

	return true;
}

template <class T>
bool AVLNode<T>::DoubleRotationLeft()
{
	assert(Left && Left->Right);

	AVLNode<T>* b = Left;
	AVLNode<T>* c = Left->Right;

	if(!IsRoot())
	{
		if (IsLeftSibling())
			Parent->Left = c;
		else
			Parent->Right = c;
	}

	// Update counters
	c->_count = _count;
	b->_count--;
	b->_count -= (c->Right ? c->Right->_count : 0);
	_count -= 2;
	_count -= (b->Left ? b->Left->_count : 0);
	_count -= (c->Left ? c->Left->_count : 0);

	// Do the switch
	b->Right = c->Left;
	Left = c->Right;
	c->Left = b;
	c->Right = this;

	// Re-align parents
	c->Parent = Parent;
	Parent = c;
	b->Parent = c;
	if(b->Right != NULL) 
		b->Right->Parent = b;
	if(Left != NULL) 
		Left->Parent = this;

	// Assume Balance == -2 before rotation is called
	// Assume b->Balance == 1 because other cases call for single rotation
	switch(c->Balance)
	{
	case -1:
		Balance = 1;
		b->Balance = 0;
		break;
	case 0:
		Balance = 0;
		b->Balance = 0;
		break;
	case 1:
		Balance = 0;
		b->Balance = -1;
		break;
	}
	c->Balance = 0;
	
	return true;
}

template <class T>
bool AVLNode<T>::DoubleRotationRight()
{
	assert(Right && Right->Left);
	
	AVLNode<T>* b = Right;
	AVLNode<T>* c = Right->Left;

	if(!IsRoot())
	{
		if(IsLeftSibling())
			Parent->Left = c;
		else
			Parent->Right = c;
	}

	// Update counters
	c->_count = _count;
	b->_count--;
	b->_count -= (c->Left ? c->Left->_count : 0);
	_count -= 2;
	_count -= (b->Right ? b->Right->_count : 0);
	_count -= (c->Right ? c->Right->_count : 0);

	// Do the switch
	Right = c->Left;
	b->Left = c->Right;
	c->Left = this;
	c->Right = b;

	// Re-align parents
	c->Parent = Parent;
	Parent = c;
	b->Parent = c;
	if(Right) 
		Right->Parent = this;
	if(b->Left)
		b->Left->Parent = b;

	// Assume Balance == 2 before rotation is called
	// Assume b->Balance == -1 because other cases call for single rotation
	switch(c->Balance)
	{
	case -1:
		Balance = 0;
		b->Balance = 1;
		break;
	case 0:
		Balance = 0;
		b->Balance = 0;
		break;
	case 1:
		Balance = -1;
		b->Balance = 0;
		break;
	}
	c->Balance = 0;

	return true;
}

template <class T>
bool AVLNode<T>::Validate() const
// Returns false if tree is out of balance. Also checks the counters.
{
	int bal = 0;
	unsigned long c = 1;
	if(Right)
	{
		if(!Right->Validate()) 
			return false;
		bal += Right->GetDepth();
		c += Right->GetCount();
	}
	if(Left)
	{
		if(!Left->Validate()) 
			return false;
		bal -= Left->GetDepth();
		c += Left->GetCount();
	}

	if(Balance != bal)
		return false;
	if(_count != c)		// also check node count
		return false;

	return true;
}

//------------------------------------------------------------------
// class AVLTree

template<class T>
class AVLTree
{
protected:
	AVLNode<T>* _root;
	AVLNode<T>* _endnode;	// dummy end marker

//	AVLNode<T>* GetRoot() { return _root;}
	void RemoveNode(AVLNode<T>* remove);
	void ReplaceNode(AVLNode<T>* remove, AVLNode<T>* replace);
	AVLNode<T>* _InternalInsertBefore(AVLNode<T>* pos, const T& data);
	AVLNode<T>* _InternalInsertAfter(AVLNode<T>* pos, const T& data);
	virtual AVLNode<T>* GetInsertPosition(const T& data, bool& before) const;
	AVLNode<T>* Insert(const T& item);
	static AVLNode<T>* CopyTree(AVLNode<T>* src, AVLNode<T>* par);
public:
	bool Validate() const
	{
		if(!empty())
			return _root->Validate();
		return true;
	}
	// STL interface-------------------------
	// basic types
	typedef T value_type;
#ifdef __STL_CONFIG_H
	typedef std::__allocator<T,alloc> allocator_type;
#else
	typedef std::allocator<T> allocator_type;
#endif
//	typedef allocator_type::size_type size_type;
	typedef _SIZT size_type;
//	typedef allocator_type::difference_type difference_type;
	typedef _PDFT difference_type;
//	typedef allocator_type::pointer pointer;
//	typedef allocator_type::const_pointer const_pointer;
//	typedef allocator_type::reference reference;
//	typedef allocator_type::const_reference const_reference;
	typedef value_type* pointer;
	typedef const value_type* const_pointer;
	typedef value_type& reference;
	typedef const value_type& const_reference;

	class AVLTree_Iterator;
	friend AVLTree_Iterator;
	class AVLTree_Iterator
	{
		friend class AVLTree<T>;
		AVLNode<T>* _pos;
		const AVLTree<T>* _over;	// identifies the tree we are iterating over

		operator AVLNode<T>*() { return _pos;}
		bool IsEnd() const { return _pos == _over->_endnode;}
	public:
		typedef T value_type;
//		typedef allocator_type::pointer pointer;
//		typedef allocator_type::const_pointer const_pointer;
//		typedef allocator_type::reference reference;
//		typedef allocator_type::const_reference const_reference;
//		typedef allocator_type::difference_type distance_type;
		typedef value_type* pointer;
		typedef const value_type* const_pointer;
		typedef value_type& reference;
		typedef const value_type& const_reference;
		typedef _PDFT distance_type;

		AVLTree_Iterator()
			: _pos(NULL), _over(NULL)
		{}
		AVLTree_Iterator(const AVLTree<T>& over, AVLNode<T>* pos = NULL) 
			: _pos(pos), _over(&over)
		{}
		AVLTree_Iterator(const AVLTree_Iterator& other) 
			: _pos(other._pos), _over(other._over)
		{}
		AVLTree_Iterator& operator=(const AVLTree_Iterator& iter)
		{
			_pos = iter._pos;
			_over = iter._over;
			return *this;
		}
		bool operator==(const AVLTree_Iterator& iter) const
		{
			return (_over == iter._over && _pos == iter._pos);
		}
		bool operator!=(const AVLTree_Iterator& iter) const
		{
			return (_pos != iter._pos || _over != iter._over);
		}
		T& GetData()
		{
			assert(_pos);
			assert(!IsEnd());
			return _pos->GetData();
		}
		const T& GetData() const
		{
			assert(_pos);
			assert(!IsEnd());
			return _pos->GetData();
		}
		void MoveNext(unsigned n = 1)
		{
			assert(n >= 0);
			if(n == 0)
				return;
			assert(_pos);
			if(IsEnd())
			{
				_pos = NULL;
				return;
			}
			_pos = _pos->GetNextNodeInOrder(n);
			if(_pos == NULL)
				_pos = _over->_endnode;
		}
		void MovePrev(unsigned n = 1)
		{
			assert(n >= 0);
			if(n == 0)
				return;
			assert(_pos);
			if(IsEnd())
			{
				assert(_over);
				assert(_over->size() >= n);
				_pos = _over->_root->GetLastNodeInTree();
				n -= 1;
			}
			_pos = _pos->GetPrevNodeInOrder(n);
		}
		void MoveTo(size_t i)
		{
			assert(_over);
			_pos = _over->_root->GetNodeInTree(i);
		}
		size_type GetIndex() const
		{
			assert(_pos);
			if(IsEnd())
			{
				assert(_over);
				return _over->_root->GetCount();
			}
			return _pos->GetIndex();
		}
	};

	typedef stl_random_access_iterator<AVLTree_Iterator> iterator;
	typedef stl_const_random_access_iterator<AVLTree_Iterator> const_iterator;

	// construction and destruction
	AVLTree()
	{
		_root = NULL;
		_endnode = new AVLNode<T>(T());		// end marker must be unique to each set
	}
	virtual ~AVLTree() 
	{
		assert(_endnode);
		delete _endnode;
		if(_root)
			delete _root;
	}
	AVLTree(const AVLTree& other)	// copy constructor
	{
		_root = CopyTree(other._root, NULL);
		_endnode = new AVLNode<T>(T());		// end marker must be unique to each set
	}
	AVLTree& operator=(const AVLTree& other)
	{
		if(&other != this)
		{
			// copy and swap
			AVLTree tmp(other);
			swap(tmp);
		}
		return *this;
	}

	// Set information
	size_type size() const { return _root ? _root->GetCount() : 0;}
	size_type max_size() const { return (size_t)-1;}
	bool empty() const { return !_root;}
	iterator begin();
	const_iterator begin() const;
	iterator end();
	const_iterator end() const;
	// No operator<() - T does not have to be less-than comparable
	//bool operator<(const AVLTree<T>& other) const;
	bool operator==(const AVLTree<T>& other) const
	{
		return (size() == other.size() && std::equal(begin(), end(), other.begin()));
	}
	// 'at' is supposed to throw an out_of_range exception
	reference at(size_type n)
	{
		assert(_root);
		AVLNode<T>* pos = _root->GetNodeInTree(n);
		assert(pos);
		return pos->GetData();
	}
	const_reference at(size_type n) const
	{
		assert(_root);
		AVLNode<T>* pos = _root->GetNodeInTree(n);
		assert(pos);
		return pos->GetData();
	}
	// operator[] is supposed to be unchecked access
	reference operator[](size_type n) { return at(n);}
	const_reference operator[](size_type n) const { return at(n);}
	reference front();
	const_reference front() const;
	reference back();
	const_reference back() const;

	void push_back(const T& item)
	{
		if(!_root)
			_root = new AVLNode<T>(item);
		else
		{
			AVLNode<T> *last = _root->GetLastNodeInTree();
			_InternalInsertAfter(last, item);
		}
	}
	void push_front(const T& item)
	{
		if(!_root)
			_root = new AVLNode<T>(item);
		else
		{
			AVLNode<T> *first = _root->GetFirstNodeInTree();
			_InternalInsertBefore(first, item);
		}
	}

	iterator erase(iterator pos);
	void clear()
	{
		if(empty())
			return;
		assert(_root);
		delete _root;
		_root = NULL;
	}

	void swap(AVLTree<T>& other)
	{
		AVLNode<T> *tmp;
		tmp = _root;
		_root = other._root;
		other._root = tmp;
		tmp = _endnode;
		_endnode = other._endnode;
		other._endnode = tmp;
	}
};

template<class T>
AVLNode<T>* AVLTree<T>::CopyTree(AVLNode<T>* src, AVLNode<T>* par)
{
	if(!src)
		return NULL;

	AVLNode<T> *copy = new AVLNode<T>(src->GetData(), par);
	if(src->Left)
		copy->Left = CopyTree(src->Left, copy);
	if(src->Right)
		copy->Right = CopyTree(src->Right, copy);
	copy->_count = src->_count;
	copy->Balance = src->Balance;
	return copy;
}

template<class T>
AVLTree<T>::iterator AVLTree<T>::begin()
{
	return AVLTree_Iterator(*this, _root ? _root->GetFirstNodeInTree() : _endnode);
}

template<class T>
AVLTree<T>::const_iterator AVLTree<T>::begin() const
{
	return AVLTree_Iterator(*this, _root ? _root->GetFirstNodeInTree() : _endnode);
}

template<class T>
AVLTree<T>::iterator AVLTree<T>::end()
{
	return AVLTree_Iterator(*this, _endnode);
}

template<class T>
AVLTree<T>::const_iterator AVLTree<T>::end() const
{
	return AVLTree_Iterator(*this, _endnode);
}

template<class T>
AVLTree<T>::reference AVLTree<T>::front()
{
	assert(!empty());
	return *begin();
}

template<class T>
AVLTree<T>::const_reference AVLTree<T>::front() const
{
	assert(!empty());
	return *begin();
}

template<class T>
AVLTree<T>::reference AVLTree<T>::back()
{
	assert(!empty());
	return *(end()-1);
}

template<class T>
AVLTree<T>::const_reference AVLTree<T>::back() const
{
	assert(!empty());
	return *(end()-1);
}

template<class T>
AVLNode<T>* AVLTree<T>::_InternalInsertBefore(AVLNode<T>* pos, const T& data)
{
AVLNode<T> *newitem;

	assert(pos);
	if(pos == _endnode)
	{
		if(!_root)
			newitem = _root = new AVLNode<T>(data);
		else
			newitem = _InternalInsertAfter(_root->GetLastNodeInTree(), data);
		assert(newitem);
		return newitem;
	}
	if(pos->Left)
	{
		pos = pos->Left->GetLastNodeInTree();
		return _InternalInsertAfter(pos, data);
	}
	// create a new node
	newitem = new AVLNode<T>(data, pos, NULL, NULL);
	assert(newitem);
	// add as left node
	pos->Left = newitem;
	// increment parent counters
	while(pos)
	{
		pos->_count++;
		pos = pos->Parent;
	}
	// restructuration
	newitem->RestructureInsert();
	_root = _root->GetRoot();
	// return the new inserted node
	return newitem;
}

template <class T>
AVLNode<T>* AVLTree<T>::_InternalInsertAfter(AVLNode<T>* pos, const T& data)
{
	assert(pos);
	assert(pos != _endnode);
	if(pos->Right)
	{
		pos = pos->Right->GetFirstNodeInTree();
		return _InternalInsertBefore(pos, data);
	}
	// create a new node
	AVLNode<T>* newitem = new AVLNode<T>(data, pos, NULL, NULL);
	// add as right node
	pos->Right = newitem;
	// increment parent counters
	while(pos)
	{
		pos->_count++;
		pos = pos->Parent;
	}
	// restructuration
	newitem->RestructureInsert();
	_root = _root->GetRoot();
	// return the new inserted node
	return newitem;
}

template<class T>
void AVLTree<T>::RemoveNode(AVLNode<T>* remove)
// Internal use only. Removes a node 'remove' from the tree and detaches
// it from its parent. The node must have no more than one child. The tree 
// is re-balanced after removal.
{
	assert(remove);
	assert(remove != _endnode);
	assert(!remove->Left || !remove->Right);

	// Get the only child of the remove node if any
	AVLNode<T>* save_child = (remove->Left ? remove->Left : remove->Right);
	if(save_child)
	{
		assert(!save_child->Left && !save_child->Right);	// should not happen
		save_child->Parent = remove->Parent;
		save_child->Balance = remove->Balance;
		save_child->_count = remove->_count;
	}

	if(remove == _root)		// removing root
	{
		_root = save_child;
	}
	else
	{
		assert(remove->Parent);
		if(remove->IsLeftSibling())
			remove->Parent->Left = save_child;
		else
			remove->Parent->Right = save_child;
	}

	// Save parent of deleted node
	AVLNode<T>* save_parent = (save_child ? save_child : remove->Parent);

	// Remove tree structure data from removed node
	remove->Parent = NULL;
	remove->Left = NULL;
	remove->Right = NULL;

	// Decrement parent counters
	AVLNode<T>* item = save_parent;
	while(item)
	{
		item->_count--;
		item = item->Parent;
	}
	// Restructure the tree
	if(save_parent)
	{
		save_parent->RestructureDelete();
		_root = _root->GetRoot();
	}
}

template<class T>
void AVLTree<T>::ReplaceNode(AVLNode<T>* remove, AVLNode<T>* replace)
// Internal use only. Removes a node 'remove' from the tree and detaches
// it from its parent and children. If 'replace' is not NULL, it is put
// into the old position. Replace must have no more than one child. If 
// 'replace' is NULL, 'remove' must have no children. The tree is 
// restructured properly in the case of a deletion.
{
	assert(remove);
	if(!replace)
	{
		RemoveNode(remove);
		return;
	}

	if(remove == replace)		// no-op
		return;

	assert(!replace->Left || !replace->Right);
	assert(replace->Parent);
	// Get the only child of the replace node if any
	AVLNode<T>* save_child = (replace->Left ? replace->Left : replace->Right);
	if(save_child)
	{
		assert(!save_child->Left && !save_child->Right);	// should not happen
		assert(save_child != remove);		// should not happen
		save_child->Parent = replace->Parent;
		save_child->Balance = replace->Balance;
		save_child->_count = replace->_count;
	}

	// Remove the replace node without restructuring.
	if(replace->IsLeftSibling())
		replace->Parent->Left = save_child;
	else
		replace->Parent->Right = save_child;

	if(remove == _root)		// removing root
		_root = replace;
	else
	{
		if(remove->IsLeftSibling())
			remove->Parent->Left = replace;
		else
			remove->Parent->Right = replace;
	}
	if(remove->Left)
		remove->Left->Parent = replace;
	if(remove->Right)
		remove->Right->Parent = replace;

	// Save parent of deleted node
	AVLNode<T>* save_parent = (save_child ? save_child : replace->Parent);
	if(save_parent == remove)
		save_parent = replace;

	// copy the old nodes tree structure data
	replace->Parent = remove->Parent;
	replace->Left = remove->Left;
	replace->Right = remove->Right;
	replace->Balance = remove->Balance;
	replace->_count = remove->_count;
	// remove tree structure data from removed node
	remove->Parent = NULL;
	remove->Left = NULL;
	remove->Right = NULL;
	remove->Balance = 0;
	remove->_count = 1;

	// Decrement parent counters
	AVLNode<T>* item = save_parent;
	while(item)
	{
		item->_count--;
		item = item->Parent;
	}
	// Restructure the tree if necessary
	if(save_parent)
	{
		save_parent->RestructureDelete();
		_root = _root->GetRoot();
	}
}

template<class T>
AVLTree<T>::iterator AVLTree<T>::erase(iterator pos)
// Removes item pointed to by 'pos' from tree and deletes it. Returns a
// pointer to the item following. Does not invalidate any iterators pointing
// to other elements in the tree.
{
	iterator nextpos = pos + 1;
	AVLNode<T>* item = (AVLNode<T>*)(AVLTree_Iterator)pos;
	assert(item);
	assert(item != _endnode);	// cannot delete end marker

	AVLNode<T> *replace = NULL;
	if(item->Left && item->Right)
	{
		replace = item->Left->GetLastNodeInTree();
		// replace->Right is NULL by definition of last node
	}
	ReplaceNode(item, replace);
	delete item;
	return nextpos;
}

template<class T>
AVLNode<T>* AVLTree<T>::GetInsertPosition(const T& item, bool& before) const
// Returns the AVL node under which the next item should be inserted. If 'before'
// returns as true, the item should be inserted before the node (left child),
// otherwise it should be inserted after the node (right child). The insert
// position is chosen so as to minimize rotation operations.
{
	assert(_root);
	AVLNode<T> *at = _root;
	while(at)
	{
		if(!at->Left)
		{
			before = true;
			return at;
		}
		if(!at->Right)
		{
			before = false;
			return at;
		}

		switch(at->Balance)
		{
		case 1:
		case 0:
			at = at->Left;
			break;
		case -1:
			at = at->Right;
			break;
		default:
			assert(false);	// should not occur
		}
	}
	assert(at);
	return at;
};

template<class T>
AVLNode<T>* AVLTree<T>::Insert(const T& item)
// Inserts an item into the tree and returns the position of the newly inserted
// item or NULL if the item could not be inserted because it is a duplicate
// and _unique is true.
{
	// Check if first item
	if(!_root)
		return _InternalInsertBefore(_endnode, item);
	
	// detect insert position
	bool before;
	AVLNode<T>* pos = GetInsertPosition(item, before);
	if(pos)
	{
		if(before)
			pos = _InternalInsertBefore(pos, item);
		else
			pos = _InternalInsertAfter(pos, item);
	}

	return pos;
};

//-----------------------------------------------------------------
// This class is same as AVLTree<T> except that a sort order is maintained
// on a binary predicate function Cmp.
template<class T, class Cmp = std::less<T> >
class Sorted_AVLTree : public AVLTree<T>
{
protected:
	Cmp _cmp;		// compare object
	bool _unique;	// true if cannot contain duplicates

	AVLNode<T>* GetInsertPosition(const T& item, bool& before) const
	{
		if(_unique)
			return GetUniqueInsertPosition(item, before);
		else
			return GetLowerInsertPosition(item, before);
	}
	AVLNode<T>* GetUniqueInsertPosition(const T& item, bool& before) const;
	AVLNode<T>* GetLowerInsertPosition(const T& item, bool& before) const;
	AVLNode<T>* GetUpperInsertPosition(const T& item, bool& before) const;
public:
	typedef AVLTree<T> base_type;
	typedef base_type::iterator iterator;
	typedef base_type::const_iterator const_iterator;
	typedef base_type::value_type value_type;
	typedef base_type::size_type size_type;

	Sorted_AVLTree(Cmp cmp = Cmp(), bool unique = false)
		: AVLTree<T>(), _cmp(cmp), _unique(unique)
	{}
	Sorted_AVLTree(const Sorted_AVLTree<T,Cmp>& other)
		: AVLTree<T>(other), _cmp(other._cmp), _unique(other._unique)
	{}
	virtual ~Sorted_AVLTree() {}
	Sorted_AVLTree<T,Cmp>& operator=(const Sorted_AVLTree<T,Cmp>& other)
	{
		if(&other != this)
		{
			AVLTree<T>::operator=(other);
			_cmp = other._cmp;
			_unique = other._unique;
		}
		return *this;
	}
	virtual bool operator<(const Sorted_AVLTree<T,Cmp>& other) const
	{
		return std::lexicographical_compare(begin(), end(), other.begin(), other.end(), _cmp);
	}
	AVLNode<T>* Find(const T& item) const;
	AVLNode<T>* LowerBound(const T& item) const;
	AVLNode<T>* UpperBound(const T& item) const;
	std::pair<AVLNode<T>*,AVLNode<T>*> EqualRange(const T& item) const;
	size_type Count(const T& item) const
	{
		size_type low, high;
		std::pair<AVLNode<T>*,AVLNode<T>*> range;

		range = EqualRange(item);
		low = (range.first == _endnode ? size() : range.first->GetIndex());
		high = (range.second == _endnode ? size() : range.second->GetIndex());

		return (high - low);
	}

	void swap(Sorted_AVLTree<T,Cmp>& other)
	{
		AVLTree<T>::swap(other);
		Cmp tmp = _cmp;
		_cmp = other._cmp;
		other._cmp = tmp;
		bool btmp = _unique;
		_unique = other._unique;
		other._unique = btmp;
	}
};

template<class T,class Cmp>
AVLNode<T>* Sorted_AVLTree<T,Cmp>::GetUniqueInsertPosition(const T& item, bool& before) const
// Returns the AVL node under which 'data' should be inserted. If 'before'
// returns as true, the item should be inserted before the node (left child),
// otherwise it should be inserted after the node (right child). Returns
// NULL if the item is already in the set.
{
	assert(_unique);
	assert(_root);
	AVLNode<T> *at = _root;
	while(1)
	{
		if(_cmp(item, at->GetData()))
		{
			if(!at->Left)
			{
				before = true;
				break;
			}
			at = at->Left;
		}
		else if(_cmp(at->GetData(), item))
		{
			if(!at->Right)
			{
				before = false;
				break;
			}
			at = at->Right;
		}
		else			// item already in set
			return NULL;
	}
	return at;
};

template<class T,class Cmp>
AVLNode<T>* Sorted_AVLTree<T,Cmp>::GetLowerInsertPosition(const T& item, bool& before) const
// Returns the AVL node under which 'data' should be inserted. If 'before'
// returns as true, the item should be inserted before the node (left child),
// otherwise it should be inserted after the node (right child). The position
// is chosen to come before any duplicates already in the set.
{
	assert(_root);
	AVLNode<T> *at = _root;
	while(1)
	{
		if(!_cmp(at->GetData(), item))
		{
			if(!at->Left)
			{
				before = true;
				break;
			}
			else
				at = at->Left;
		}
		else
		{
			if(!at->Right)
			{
				before = false;
				break;
			}
			else
				at = at->Right;
		}
	}
	return at;
};

template<class T,class Cmp>
AVLNode<T>* Sorted_AVLTree<T,Cmp>::GetUpperInsertPosition(const T& item, bool& before) const
// Returns the AVL node under which 'data' should be inserted. If 'before'
// returns as true, the item should be inserted before the node (left child),
// otherwise it should be inserted after the node (right child). The position
// is chosen to come after any duplicates already in the set.
{
	assert(_root);
	AVLNode<T> *at = _root;
	while(1)
	{
		if(_cmp(item, at->GetData()))
		{
			if(!at->Left)
			{
				before = true;
				break;
			}
			else
				at = at->Left;
		}
		else
		{
			if(!at->Right)
			{
				before = false;
				break;
			}
			else
				at = at->Right;
		}
	}
	return at;
};

template<class T,class Cmp>
AVLNode<T>* Sorted_AVLTree<T,Cmp>::Find(const T& item) const
// Returns the position of the first item in the tree that matches 'data'
// or NULL if no match is found.
{
	AVLNode<T> *at = _root;
	while(at)
	{
		if(_cmp(item, at->GetData()))
		{
			at = at->Left;
		}
		else
		{
			if(!_cmp(at->GetData(), item))		// match found
				return at;
			at = at->Right;
		}
	}
	return NULL;		// no match found
}

template<class T,class Cmp>
AVLNode<T>* Sorted_AVLTree<T,Cmp>::LowerBound(const T& item) const
// Returns a pointer to the first node in the tree which is greater than or
// equal to 'item'. If 'item' is greater than all the nodes, returns _endnode.
{
	AVLNode<T> *lower = _endnode;
	AVLNode<T> *at = _root;
	while(at)
	{
		if(!_cmp(at->GetData(), item))
		{
			lower = at;
			at = at->Left;
		}
		else
		{
			at = at->Right;
		}
	}
	return lower;
};

template<class T,class Cmp>
AVLNode<T>* Sorted_AVLTree<T,Cmp>::UpperBound(const T& item) const
// Returns a pointer to the first node in the tree which is greater than 'item'.
// If 'item' is greater than or equal to all the nodes, returns _endnode.
{
	AVLNode<T> *upper = _endnode;
	AVLNode<T> *at = _root;
	while(at)
	{
		if(_cmp(item, at->GetData()))
		{
			upper = at;
			at = at->Left;
		}
		else
		{
			at = at->Right;
		}
	}
	return upper;
};

template<class T,class Cmp>
std::pair<AVLNode<T>*,AVLNode<T>*> Sorted_AVLTree<T,Cmp>::EqualRange(const T& item) const
// Returns the lower and upper bounds of 'item'. See LowerBound and UpperBound functions.
{
	AVLNode<T> *lower = _endnode, *upper = _endnode, *backtrack = NULL;
	AVLNode<T> *at = _root;
	while(at)
	{
		if(_cmp(item, at->GetData()))
		{
			lower = at;
			upper = at;
			at = at->Left;
		}
		else if(!_cmp(at->GetData(), item))	// match found
		{
			lower = at;
			if(!backtrack)
				backtrack = at->Right;		// save this for upper search
			at = at->Left;
		}
		else
		{
			at = at->Right;
		}
	}

	// Now go back and find the upper node
	at = backtrack;
	while(at)
	{
		if(_cmp(item, at->GetData()))
		{
			upper = at;
			at = at->Left;
		}
		else
		{
			at = at->Right;
		}
	}
	return std::make_pair(lower, upper);
};

//------------------------------------------------------------------
// STL containers

// An index_list is a sequence which combines the interfaces of array, deque,
// and list. Here are the comparisons:
//					array	deque	list	index_list
// indexed access:	1		1		(N)		lgN
// insert/delete:	N		N		1		1+
// front insertion:	(N)		1+		1		1+
// back insertion	1+		1+		1		1+
// It tends to work best for large sets (N >> 1).
// It also has the extra function insert(const T&), usually used for sets,
// which chooses an insert position which keeps the tree balance with a
// minimal number of rotation operations.

template<class T>
class index_list : public AVLTree<T>
{
public:
	index_list()
		: AVLTree<T>()
	{}
	index_list(const index_list& other)
		: AVLTree<T>(other)
	{}
	index_list(size_t n, const T& item = T())
	{
		for(size_t i = 0; i < n; i++)
			Insert(item);
	}
	index_list(const_iterator first, const_iterator last)
	{
		for(const_iterator at = first; at != last; ++at)
			_InternalInsertBefore(_endnode, *at);	// preserve order
	}
	virtual ~index_list() {}

	iterator insert(iterator at, const T& item);
	iterator insert(const T& item);
};

template<class T>
index_list<T>::iterator index_list<T>::insert(const T& item)
{
	AVLNode<T> *pos = Insert(item);
	assert(pos);
	return AVLTree_Iterator(*this, pos);
};

template<class T>
index_list<T>::iterator index_list<T>::insert(iterator at, const_reference data)
{
	AVLNode<T> *pos = (AVLNode<T>*)(AVLTree_Iterator)at;
	assert(pos);
	pos = _InternalInsertBefore(pos, data);
	return AVLTree_Iterator(*this, pos);
}


//----------------------------------------------------------------
// An index_set implements the STL interface for set with the addition
// of indexed access (operator[n], at(n)).
// Here are the comparisons with other sorted structures.
//					array	list	set		index_set
// indexed access:	1		(N)		(N+)	lgN
// insert/delete:	N		1		1+		1+
// search:			lgN		N		lgN		lgN

// 'T' is the element type and 'Cmp' is the ordering function, which is a
// binary predicate functor.
template<class T, class Cmp = std::less<T> >
class index_set : public Sorted_AVLTree<T,Cmp>
{
public:
	typedef T key_type;
	typedef T value_type;
	typedef Cmp key_compare;
	typedef Cmp value_compare;
	key_compare key_comp() { return _cmp;}
	value_compare value_comp() { return _cmp;}

	index_set(const Cmp& pred = Cmp()) 
		: Sorted_AVLTree<T,Cmp>(pred, true)
	{}
	index_set(const index_set& other)
		: Sorted_AVLTree<T,Cmp>(other)
	{}
	index_set(const_iterator first, const_iterator last, const Cmp& pred = Cmp())
		: Sorted_AVLTree<T,Cmp>(pred, true)
	{
		for(const_iterator at = first; at != last; at++)
			Insert(*at);
	}
	virtual ~index_set() {}

	std::pair<iterator,bool> insert(const value_type& item);
	const_iterator find(const T& item) const
	{
		AVLNode<T> *pos = Find(item);
		if(!pos)
			pos = _endnode;
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator lower_bound(const T& item) const
	{
		AVLNode<T> *pos = LowerBound(item);
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator upper_bound(const T& item) const
	{
		AVLNode<T> *pos = UpperBound(item);
		return AVLTree_Iterator(*this, pos);
	}
	std::pair<const_iterator,const_iterator> equal_range(const T& item) const
	{
		std::pair<AVLNode<T>*,AVLNode<T>*> range = EqualRange(item);
		return std::make_pair(const_iterator(AVLTree_Iterator(*this, range.first)), 
			const_iterator(AVLTree_Iterator(*this, range.second)));
	}
	size_type count(const T& item) const
	{
		return Count(item);
	}
};

template<class T,class Cmp>
std::pair<index_set<T,Cmp>::iterator,bool> index_set<T,Cmp>::insert(const value_type& item)
// Inserts an item into the set. Returns end of sequence and false if the item is
// already in the set, otherwise returns a pointer to the item inserted and true.
{
	AVLNode<T> *pos = Insert(item);
	bool found = (pos ? true: false);
	return std::make_pair(AVLTree_Iterator(*this, pos), found);
}

//----------------------------------------------------------------
// An index_multiset implements the STL interface for multiset with the
// addition of indexed access (operator[n], at(n)). Performance characteristics
// are the same as with index_set.

template<class T, class Cmp = std::less<T> >
class index_multiset : public Sorted_AVLTree<T,Cmp>
{
public:
	typedef T key_type;
	typedef T value_type;
	typedef Cmp key_compare;
	typedef Cmp value_compare;
	key_compare key_comp() { return _cmp;}
	value_compare value_comp() { return _cmp;}

	index_multiset(const Cmp& pred = Cmp()) 
		: Sorted_AVLTree<T,Cmp>(pred, false)
	{}
	index_multiset(const index_multiset& other)
		: Sorted_AVLTree<T,Cmp>(other)
	{}
	index_multiset(size_t n, const T& item = T(), const Cmp& pred = Cmp())
		: Sorted_AVLTree<T,Cmp>(pred, false)
	{
		for(size_t i = 0; i < n; i++)
			Insert(item);
	}
	index_multiset(const_iterator first, const_iterator last, const Cmp& pred = Cmp())
		: Sorted_AVLTree<T,Cmp>(pred, false)
	{
		for(const_iterator at = first; at != last; at++)
			Insert(*at);
	}
	virtual ~index_multiset() {}

	iterator insert(const value_type& item);
	const_iterator find(const T& item) const
	{
		AVLNode<T> *pos = Find(item);
		if(!pos)
			pos = _endnode;
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator lower_bound(const T& item) const
	{
		AVLNode<T> *pos = LowerBound(item);
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator upper_bound(const T& item) const
	{
		AVLNode<T> *pos = UpperBound(item);
		return AVLTree_Iterator(*this, pos);
	}
	std::pair<const_iterator,const_iterator> equal_range(const T& item) const
	{
		std::pair<AVLNode<T>*,AVLNode<T>*> range = EqualRange(item);
		return std::make_pair(const_iterator(AVLTree_Iterator(*this, range.first)), 
			const_iterator(AVLTree_Iterator(*this, range.second)));
	}
	size_type count(const T& item) const
	{
		return Count(item);
	}
};

template<class T,class Cmp>
index_multiset<T,Cmp>::iterator index_multiset<T,Cmp>::insert(const value_type& item)
// Inserts an item into the set. Returns a pointer to the item inserted.
// The item is inserted before any duplicates already in the set.
{
	AVLNode<T> *at = Insert(item);
	assert(at);
	return AVLTree_Iterator(*this, at);
};


//-----------------------------------------------------------------
// An index_map implements the STL interface for map, with the addition
// of indexed access (operator[n], at(n)). Performance characteristics
// are the same as with index_set.

// This provides a value compare class given the key compare type 'Cmp'.
template<class Key, class T, class Cmp>
class ValueCompare : public std::binary_function<std::pair<const Key,T>,std::pair<const Key,T>,bool>
{
	Cmp _cmp;
public:
	ValueCompare(const Cmp cmp = Cmp())
		: _cmp(cmp) {}
	bool operator()(const std::pair<const Key,T>& v1, const std::pair<const Key,T>& v2) const
	{
		return _cmp(v1.first, v2.first);
	}
};

template<class Key, class T, class Cmp = std::less<Key> >
class index_map : public Sorted_AVLTree<std::pair<const Key,T>,ValueCompare<Key,T,Cmp> >
{
	Cmp _keycmp;
public:
	typedef Key key_type;
	typedef T mapped_type;

	typedef Cmp key_compare;
	typedef ValueCompare<Key,T,Cmp> value_compare;
	key_compare key_comp() { return _keycmp;}
	value_compare value_comp() { return _cmp;}

	typedef Sorted_AVLTree<std::pair<const Key,T>,ValueCompare<Key,T,Cmp> > base_type;
	typedef base_type::iterator iterator;
	typedef base_type::const_iterator const_iterator;
	typedef base_type::value_type value_type;
	typedef base_type::size_type size_type;

	index_map(const Cmp& pred = Cmp())
		: _keycmp(pred), Sorted_AVLTree<value_type,value_compare>(value_compare(pred), true)
	{}
	index_map(const index_map& other)
		: _keycmp(other._keycmp), Sorted_AVLTree<value_type,value_compare>(other)
	{}
	index_map(const_iterator first, const_iterator last, const Cmp& pred = Cmp())
		: _keycmp(pred), Sorted_AVLTree<value_type,value_compare>(value_compare(pred), true)
	{
		for(const_iterator at = first; at != last; at++)
			Insert(*at);
	}
	virtual ~index_map() {}

	std::pair<iterator,bool> insert(const value_type& item);
	const_iterator find(const Key& key) const
	{
		AVLNode<std::pair<const Key,T> > *pos = Find(std::pair<const Key,T>(key,T()));
		if(!pos)
			pos = _endnode;
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator lower_bound(const Key& key) const
	{
		AVLNode<std::pair<const Key,T> > *pos = LowerBound(std::pair<const Key,T>(key,T()));
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator upper_bound(const Key& key) const
	{
		AVLNode<std::pair<const Key,T> > *pos = UpperBound(std::pair<const Key,T>(key,T()));
		return AVLTree_Iterator(*this, pos);
	}
	std::pair<const_iterator,const_iterator> equal_range(const Key& key) const
	{
		std::pair<AVLNode<std::pair<const Key,T> >*,AVLNode<std::pair<const Key,T> >*> range = EqualRange(std::pair<const Key,T>(key,T()));
		return std::make_pair(const_iterator(AVLTree_Iterator(*this, range.first)), 
			const_iterator(AVLTree_Iterator(*this, range.second)));
	}
	size_type count(const Key& key) const
	{
		return Count(std::pair<const Key,T>(key,T()));
	}

	void swap(index_map& other)
	{
		Sorted_AVLTree<value_type,value_compare>::swap(other);
		Cmp tmp = _keycmp;
		_keycmp = other._keycmp;
		other._keycmp = tmp;
	}
};

template<class Key,class T,class Cmp>
std::pair<index_map<Key,T,Cmp>::iterator,bool> index_map<Key,T,Cmp>::insert(const value_type& item)
// Inserts an item into the set. Returns end of sequence and false if the item is
// already in the set, otherwise returns a pointer to the item inserted and true.
{
	AVLNode<std::pair<const Key,T> > *pos = Insert(item);
	bool found = (pos ? true : false);
	return std::make_pair(index_map<Key,T,Cmp>::iterator(AVLTree_Iterator(*this, pos)), found);
}


//-----------------------------------------------------------------
// An index_multimap implements the STL interface for multimap, with the
// addition of indexed access (operator[n], at(n)). Performance characteristics
// are the same as with index_set.

template<class Key, class T, class Cmp = std::less<Key> >
class index_multimap : public Sorted_AVLTree<std::pair<const Key,T>,ValueCompare<Key,T,Cmp> >
{
	Cmp _keycmp;
public:
	typedef T mapped_type;
	typedef Key key_type;

	typedef Cmp key_compare;
	typedef ValueCompare<Key,T,Cmp> value_compare;
	key_compare key_comp() { return _keycmp;}
	value_compare value_comp() { return _cmp;}

	typedef Sorted_AVLTree<std::pair<const Key,T>,ValueCompare<Key,T,Cmp> > base_type;
	typedef base_type::iterator iterator;
	typedef base_type::const_iterator const_iterator;
	typedef base_type::value_type value_type;
	typedef base_type::size_type size_type;

	index_multimap(const Cmp& pred = Cmp())
		: _keycmp(pred), Sorted_AVLTree<value_type,value_compare>(value_compare(pred), false)
	{}
	index_multimap(const index_multimap& other)
		: _keycmp(other._keycmp), Sorted_AVLTree<value_type,value_compare>(other)
	{}
	index_multimap(const_iterator first, const_iterator last, const Cmp& pred = Cmp())
		: _keycmp(pred), Sorted_AVLTree<value_type,value_compare>(value_compare(pred), false)
	{
		for(const_iterator at = first; at != last; at++)
			Insert(*at);
	}
	virtual ~index_multimap() {}

	iterator insert(const value_type& item);
	const_iterator find(const Key& key) const
	{
		AVLNode<std::pair<const Key,T> > *pos = Find(std::pair<const Key,T>(key,T()));
		if(!pos)
			pos = _endnode;
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator lower_bound(const Key& key) const
	{
		AVLNode<std::pair<const Key,T> > *pos = LowerBound(std::pair<const Key,T>(key,T()));
		return AVLTree_Iterator(*this, pos);
	}
	const_iterator upper_bound(const Key& key) const
	{
		AVLNode<std::pair<const Key,T> > *pos = UpperBound(std::pair<const Key,T>(key,T()));
		return AVLTree_Iterator(*this, pos);
	}
	std::pair<const_iterator,const_iterator> equal_range(const Key& key) const
	{
		std::pair<AVLNode<std::pair<const Key,T> >*,AVLNode<std::pair<const Key,T> >*> range = EqualRange(std::pair<const Key,T>(key,T()));
		return std::make_pair(const_iterator(AVLTree_Iterator(*this, range.first)), 
			const_iterator(AVLTree_Iterator(*this, range.second)));
	}
	size_type count(const Key& key) const
	{
		return Count(std::pair<const Key,T>(key,T()));
	}

	void swap(index_multimap& other)
	{
		Sorted_AVLTree<value_type,value_compare>::swap(other);
		Cmp tmp = _keycmp;
		_keycmp = other._keycmp;
		other._keycmp = tmp;
	}
};

template<class Key,class T,class Cmp>
index_multimap<Key,T,Cmp>::iterator index_multimap<Key,T,Cmp>::insert(const value_type& item)
// Inserts an item into the set. Returns a pointer to the item inserted.
// The item is inserted before any duplicates already in the set.
{
	AVLNode<std::pair<const Key,T> > *pos = Insert(item);
	assert(pos);
	return AVLTree_Iterator(*this, pos);
};

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions