/*-*-c++-*-
 * $Id: avl.cpp,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.
 */
#ifdef AVL_H

#include <cassert>
#include <cstdio>

template<class T>
Avl<T>::Avl(bool multiset)
			: oRoot(0)
			, oMultiset(multiset)
{
}

template<class T>
Avl<T>::~Avl()
{
	destroy(oRoot);
	oRoot = 0;
}

template<class T> void
Avl<T>::destroy(AvlNode<T>* parent)
{
	if (parent == 0)
		return;
	
	destroy(parent->left);
	destroy(parent->right);
	delete parent;
}

template<class T> const T*
Avl<T>::insert(const T& key)
{
	oInserted	= false;
	oGrown		= false;
	oRoot		= insert_priv(oRoot, key);
		
	return oInsertedKey;
}

template<class T> AvlNode<T>*
Avl<T>::insert_priv(AvlNode<T>* node, const T& key)
{
	if (node == 0) {
		node		= new AvlNode<T>(key);
		oInserted	= true;
		oGrown		= true;
		oInsertedKey= &node->next->key;
		
		return node;
	}
	
	if (node->next->key < key) {
		node->right			= insert_priv(node->right, key);
		node->right->parent	= node;
		
		if (oGrown)
			switch (node->bf) {
				case -1:
					node->bf	= 0;
					oGrown		= false;
					break;
					
				case 0:
					node->bf	= 1;
					break;
					
				case 1:
					node		= balanceRight(node);
					oGrown		= false;
					break;
			}
	}
	else if (node->next->key > key) {
		node->left			= insert_priv(node->left, key);
		node->left->parent	= node;
		
		if (oGrown)
			switch (node->bf) {
				case -1:
					node		= balanceLeft(node);
					oGrown		= false;
					break;
					
				case 0:
					node->bf	= -1;
					break;
					
				case 1:
					node->bf	= 0;
					oGrown		= false;
					break;
			}
	}
	else if (oMultiset) { // keys are equal
		AvlList<T>* ln	= new AvlList<T>(key);
		ln->next	= node->next;
		node->next	= ln;
		oInserted	= true;
		oGrown		= false;
		oInsertedKey= &node->next->key;
	}
	else
		oInsertedKey = 0;
	
	return node;
}

template<class T> bool
Avl<T>::remove(const T& key)
{
	/* remove the first key with an equal value to this key */
	oExact		= false;
	oRemoved	= false;
	oShrunk		= false;
	oRoot		= remove_priv(oRoot, &key);
	
	return oRemoved;
}

template<class T> bool
Avl<T>::removeKey(const T* key)
{
	/* remove exactly this key */
	oExact		= true;
	oRemoved	= false;
	oShrunk		= false;
	oRoot		= remove_priv(oRoot, key);
	
	return oRemoved;
}

template<class T> AvlNode<T>*
Avl<T>::remove_priv(AvlNode<T>* node, const T* key)
{
	if (node == 0)
		return 0;
	
	if (node->next->key < *key) {
		node->right = remove_priv(node->right, key);
		
		if (oShrunk) {
			switch (node->bf) {
				case 0:
					node->bf	= -1;
					oShrunk		= false;
					break;
				
				case 1:
					node->bf	= 0;
					break;
				
				case -1:
					node	= balanceLeft(node);
					oShrunk	= false;
					break;
			}
		}
	}
	else if (node->next->key > *key) {
		node->left = remove_priv(node->left, key);
		if (oShrunk) {
			switch (node->bf) {
				case 0:
					node->bf	= 1;
					oShrunk		= false;
					break;
				
				case -1:
					node->bf	= 0;
					break;
				
				case 1:
					node	= balanceRight(node);
					oShrunk	= false;
					break;
			}
		}
	}
	else { // found equal key
		if (oExact && key != &(node->next->key)) {
			AvlList<T>* walker	= node->next->next;
			AvlList<T>* prev	= node->next;
			
			while (walker != 0) {
				if (&(walker->key) == key) {
					prev->next = walker->next;
					delete walker;
					oRemoved = true;
					break;
				}
				
				prev	= walker;
				walker	= walker->next;
			}
		}
		else if (node->next->next != 0) {
			AvlList<T>* prev = node->next;
			node->next = node->next->next;
			delete prev;
			oRemoved = true;
		}
		else { // delete node
			if ((node->left != 0) && (node->right != 0)) {
				// there is two children -> replace this node by its predecessor
				AvlNode<T>* pre		= predecessor(node);
				AvlList<T>* tmp		= new AvlList<T>(pre->next->key); // will be deleted in remove_priv()
				AvlList<T>* preList	= pre->next;
				pre->next		= tmp;
				
				// now delete predecessor
				node->left = remove_priv(node->left, &(tmp->key));
				assert(oRemoved == true);
				delete node->next;
				node->next = preList;
				
				// tree may be unbalanced at this level
				if (oShrunk) {
					switch (node->bf) {
						case 0:
							node->bf	= 1;
							oShrunk		= false;
							break;
						
						case -1:
							node->bf	= 0;
							break;
						
						case 1:
							node	= balanceRight(node);
							oShrunk	= false;
							break;
					}
				}
			}
			else {
				if (node->left != 0) { // only left child
					AvlNode<T>* child		= node->left;
					child->parent	= node->parent;
					delete node;
					node = child;
				}
				else if (node->right != 0) { // only right child
					AvlNode<T>* child		= node->right;
					child->parent	= node->parent;
					delete node;
					node = child;
				}
				else { // no child at all
					delete node;
					node = 0;
				}
			
				oRemoved	= true;
				oShrunk		= true;
			}
		}
	}
	
	return node;
}

template<class T> AvlNode<T>*
Avl<T>::rotateLeft(AvlNode<T>* node)
{
	AvlNode<T>* rn = node->right;
	
	node->right		= rn->left;
	rn->left		= node;
	rn->parent		= node->parent;
	node->parent	= rn;
	if (node->right != 0)
		node->right->parent = node;
	
	return rn;
}

template<class T> AvlNode<T>*
Avl<T>::rotateRight(AvlNode<T>* node)
{
	AvlNode<T>* ln = node->left;
	
	node->left		= ln->right;
	ln->right		= node;
	ln->parent		= node->parent;
	node->parent	= ln;
	if (node->left != 0)
		node->left->parent = node;
	
	return ln;
}

template<class T> AvlNode<T>*
Avl<T>::balanceLeft(AvlNode<T>* node)
{
	AvlNode<T>* ln = node->left;
	
	if (ln->bf == (char) -1) {
		node->bf	= 0;
		ln->bf		= 0;
		node		= rotateRight(node);
	}
	else if (ln->bf == 1) {
		switch (ln->right->bf) {
			case 0:
				node->bf	= 0;
				ln->bf		= 0;
				break;
			
			case -1:
				node->bf	= 1;
				ln->bf		= 0;
				break;
			
			case 1:
				node->bf	= 0;
				ln->bf		= -1;
				break;
		}
		
		ln->right->bf	= 0;
		node->left		= rotateLeft(ln);
		node			= rotateRight(node);
	}
	else { // left child (ln) is balanced (this happens only during deletion)
		ln->bf		= 1;
		node		= rotateRight(node);
	}
	
	return node;
}

template<class T> AvlNode<T>*
Avl<T>::balanceRight(AvlNode<T>* node)
{
	AvlNode<T>* rn = node->right;
	
	if (rn->bf == 1) {
		node->bf	= 0;
		rn->bf		= 0;
		node		= rotateLeft(node);
	}
	else if (rn->bf == (char) -1) {
		switch (rn->left->bf) {
			case 1:
				node->bf	= -1;
				rn->bf		= 0;
				break;
			
			case 0:
				node->bf	= 0;
				rn->bf		= 0;
				break;
			
			case -1:
				node->bf	= 0;
				rn->bf		= 1;
		}
		
		rn->left->bf	= 0;
		node->right		= rotateRight(rn);
		node			= rotateLeft(node);
	}
	else { // rn is balanced (deletion)
		rn->bf		= -1;
		node		= rotateLeft(node);
	}
	
	return node;
}

template<class T> AvlIterator<T>
Avl<T>::find(const T& key, bool exact)
{
	AvlIterator<T> it;
	
	oExact = exact;
	AvlNode<T>* node = search_priv(oRoot, key);
	
	if (node != 0) {
		it.node = node;
		it.list = node->next;
	}

	return it;
}

template<class T> bool
Avl<T>::search(const T& key, T** retPtr, bool exact)
{
	oExact = exact;
	AvlNode<T>* node = search_priv(oRoot, key);
	
	if (node == 0)
		return false;
	
	if (retPtr != 0)
		*retPtr = &(node->next->key);
	
	return true;
}

template<class T> AvlNode<T>*
Avl<T>::search_priv(AvlNode<T>* parent, const T& key)
{
	if (parent == 0)
		return 0;
	
	if (parent->next->key < key)
		return search_priv(parent->right, key);
	else if (parent->next->key > key) {
		AvlNode<T>* node = search_priv(parent->left, key);
		
		if (node == 0 && oExact == false)
			node = parent;
		
		return node;
	}
	
	return parent;
}

template<class T> void
Avl<T>::print() const
{
	print_priv(oRoot);
}

template<class T> void
Avl<T>::print_priv(AvlNode<T>* node) const
{
	if (node == 0)
		return;
	
	std::cout << "key=" << node->next->key << " ";
	std::printf("this=%p (left=%p right=%p) bf=%d\n"
				, node
				, node->left
				, node->right
				, (int)node->bf
	);
	print_priv(node->left);
	print_priv(node->right);
}

template<class T> AvlNode<T>*
Avl<T>::predecessor(const AvlNode<T>* parent) const
{
	AvlNode<T>* walker = parent->left;
	
	while (walker->right != 0)
		walker = walker->right;
	
	return walker;
}

template<class T> AvlIterator<T>
Avl<T>::begin() const
{
	AvlIterator<T> it;
	AvlNode<T>* walker = oRoot;
	
	if (walker != 0)
		while (true)
			if (walker->left != 0)
				walker = walker->left;
			else
				break;
	
	it.node = walker;
	it.list = (walker != 0) ? walker->next : 0;
	
	return it;
}

template<class T> AvlIterator<T>
Avl<T>::end() const
{
	AvlIterator<T> it;
	it.node = 0;
	it.list = 0;
	
	return it;
}

template<class T> void
Avl<T>::clear()
{
	destroy(oRoot);
	oRoot = 0;
}

template<class L>
AvlList<L>::AvlList(const L& k) : key(k), next(0)
{
}

template<class L>
AvlList<L>::~AvlList()
{
}

template<class L> void
AvlList<L>::dispose()
{
	AvlList* walker = this;
	while (walker != 0) {
		AvlList* prev = walker;
		walker = walker->next;
		delete prev;
	}
}

template<class N>
AvlNode<N>::AvlNode(const N& k)
			: left(0)
			, right(0)
			, parent(0)
			, next(new AvlList<N>(k))
			, bf(0)
{
}

template<class N>
AvlNode<N>::~AvlNode()
{
	AvlList<N>* walker = next;
	
	while (walker != 0) {
		AvlList<N>* prev = walker;
		walker = walker->next;
		
		delete prev;
	}
}

/*********************************************************************/

template<class T>
AvlIterator<T>::AvlIterator() : node(0), list(0)
{
}

template<class T>
AvlIterator<T>::AvlIterator(const Avl<T>* tree)
{
	*this = tree->begin();
}

template<class T>
AvlIterator<T>::~AvlIterator()
{
}

template<class T> T&
AvlIterator<T>::operator*()
{
	return list->key;
}

template<class T> T*
AvlIterator<T>::operator->()
{
	return &list->key;
}

template<class T> AvlIterator<T>&
AvlIterator<T>::operator++()
{
	next();
	
	return *this;
}

template<class T> AvlIterator<T>
AvlIterator<T>::operator++(int)
{
	AvlIterator<T> tmp(*this);
	
	next();
	
	return tmp;
}

template<class T> void
AvlIterator<T>::next()
{
	if (list->next != 0) {
		list = list->next;
		return;
	}
	
	if (node->right != 0) {
		AvlNode<T>* walker = node->right;
		while (walker->left != 0)
			walker = walker->left;
		node = walker;
		list = walker->next;
		
		return;
	}
	
	AvlNode<T>* parent	= node->parent;
	AvlNode<T>* child		= node;
	
	while (parent != 0) {
		if (child == parent->left) {
			node = parent;
			list = parent->next;
			return;
		}
		
		child	= parent;
		parent	= parent->parent;
	}
	
	node = 0;
	list = 0;
}

template<class T> bool
operator==(const AvlIterator<T>& x, const AvlIterator<T>& y)
{
	return (x.node == y.node && x.list == y.list);
}

template<class T> bool
operator!=(const AvlIterator<T>& x, const AvlIterator<T>& y)
{
	return (x.node != y.node || x.list != y.list);
}

#endif
