/*-*-c++-*-
 * $Id: avl.h,v 1.1 2002/01/28 15:38:32 holzheu Exp $
 *
 * This file is part of qlcrash, a GUI for the dump-analysis tool lcrash.
 *
 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *
 * Authors:
 * Michael Geselbracht (let@users.sourceforge.net)
 * Fritz Elfert (elfert@de.ibm.com)
 * Michael Holzheu (holzheu@de.ibm.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */
#ifndef AVL_H
#define AVL_H

#include "osdep.h"

template<class T> class AvlIterator;
template<class T> class Avl;
template<class T> class AvlNode;
/** An Avl-tree implementation that can be configured to act either
  * like a set or like a multiset
  * @author Michael Geselbracht
  */


template<class L>
class AvlList {
public:
	AvlList(const L& key);
	~AvlList();
	
	/* Dispose the whole list. Note that this occurs recusivly, so do not
      delete a long list this way.
     */
	void dispose();
	
	L			key;
	AvlList<L>*	next;
};

template<class N>
class AvlNode {
public:
	AvlNode(const N& key);
	~AvlNode();
		
	AvlNode<N>*	left;
	AvlNode<N>*	right;
	AvlNode<N>*	parent;
	AvlList<N>*	next;
	char		bf;
};

template<class T>
class Avl {
	friend class AvlIterator<T>;
		
public:
	typedef const AvlIterator<T> const_iterator;
	typedef AvlIterator<T> iterator;
	
#if 0
	/** A linked list is used to store multiple keys within the same node
	*/
	struct List {
		List(const T& key);
		~List();
		
		/* Dispose the whole list. Note that this occurs recusivly, so do not
	      delete a long list this way.
	     */
		void dispose();
		
		T		key;
		List*	next;
	};
#endif

	/** Create an empty tree */
	Avl(bool multiset=true);
	~Avl();
	
	/** Insert a new key */
	const T* insert(const T& key);
	
	/** Remove a key */
	bool remove(const T& key);
	
	/** Remove key which address is `keyPtr'. This may be useful if the tree is configured
	  * to behave like a multiset and you want to remove a special key.
	  */
	bool removeKey(const T* keyPtr);
	
	/** Search a key. A pointer to the stored key is stored in `retPtr' if it is not null */
	bool search(const T& key, T** retPtr=0, bool exact=true);
	
	/** Print contents of tree (for debugging purposes - only int is supported) */
	void print() const;
	
	AvlIterator<T> begin() const;
	AvlIterator<T> end() const;
	AvlIterator<T> find(const T&, bool exact=true);
	
	/** Clear the whole tree */
	void clear();

protected:
	AvlNode<T>*		oRoot;
	
private:

	/** no copy constructor */
	Avl(const Avl<T>&);
	
	/** no assignment */
	Avl& operator=(const Avl<T>&);
	
	/** insert key recursivly*/
	AvlNode<T>* insert_priv(AvlNode<T>* parent, const T& key);
	
	/** remove a key recursivly. a pointer to the key is used to enable the
	  * removing a exactly that key (seel removeKey()) */
	AvlNode<T>* remove_priv(AvlNode<T>* parent, const T* key);
	
	/* balancing */
	AvlNode<T>* rotateLeft(AvlNode<T>*);
	AvlNode<T>* rotateRight(AvlNode<T>*);
	AvlNode<T>* balanceLeft(AvlNode<T>*);
	AvlNode<T>* balanceRight(AvlNode<T>*);
	
	/* delete the whole tree */
	void destroy(AvlNode<T>*);
	
	/* find the predecessor of `parent' (which must exist) */
	AvlNode<T>* predecessor(const AvlNode<T>* parent) const;
	
	AvlNode<T>* search_priv(AvlNode<T>* parent, const T& key);
	void print_priv(AvlNode<T>*) const;
	
	bool		oMultiset;
	bool		oInserted;
	bool		oGrown;
	bool		oShrunk;
	bool		oRemoved;
	bool		oExact;
	const T*	oInsertedKey;
};

template<class T> bool operator==(const AvlIterator<T>&, const AvlIterator<T>&);
template<class T> bool operator!=(const AvlIterator<T>&, const AvlIterator<T>&);

template<class T>
class AvlIterator {
	friend class Avl<T>;
#ifdef WIN32
	friend bool operator==(const AvlIterator<T>&, const AvlIterator<T>&);
	friend bool operator!=(const AvlIterator<T>&, const AvlIterator<T>&);
#else
	friend bool operator==<T>(const AvlIterator<T>&, const AvlIterator<T>&);
	friend bool operator!=<T>(const AvlIterator<T>&, const AvlIterator<T>&);
#endif


public:
	AvlIterator();
	AvlIterator(const Avl<T> *);
	~AvlIterator();
	
	AvlIterator<T>& operator++();
	AvlIterator<T> operator++(int);
	T& operator*();
	T* operator->();

private:
	void next();
	
	AvlNode<T>* node;
	AvlList<T>* list;
};

#include "avl.cpp"

#endif
