/*
Copyright (C) 1997, 1998, 1999, 2000 by Alex Pfaffe
(Digital Dawn Graphics Inc)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ddgSplay_Class_
#define _ddgSplay_Class_
#include "util/ddgerror.h"
class WEXP ddgSplayKey
{
unsigned int _key;
union {
unsigned int _value;
struct {
unsigned short _tree;
unsigned short _index;
} _ti;
};
public:
inline ddgSplayKey( void ) : _key(0), _value(0) { }
inline ddgSplayKey( unsigned int tree, unsigned int tindex, unsigned int priority )
{_key = priority; _ti._index = tindex; _ti._tree = tree; }
inline void set( ddgSplayKey sk )
{ _key = sk._key; _ti._index = sk._ti._index; _ti._tree = sk._ti._tree; }
inline int compare( ddgSplayKey sk )
{
if (_key < sk._key) return -1;
if (_key > sk._key) return 1;
if (_value < sk._value) return -1;
if (_value > sk._value) return 1;
// They are equal.
return 0;
}
inline unsigned int index(void)
{
return _ti._index;
}
inline unsigned int tree(void)
{
return _ti._tree;
}
inline unsigned int key(void)
{
return _key;
}
};
// 16 bit index allows for ddgSplay trees to maintain up to ~65000 entries.
class ddgSplayTree;
class ddgSplayIterator;
class ddgSplayNode;
typedef ddgSplayNode *ddgSplayIndex;
class WEXP ddgSplayNode
{
friend ddgSplayTree;
friend ddgSplayIterator;
ddgSplayKey _key;
ddgSplayIndex _left;
ddgSplayIndex _right;
public:
inline void set( ddgSplayKey k ) { _key.set(k); }
};
class WEXP ddgSplayTree
{
static ddgSplayIndex _nList;
static ddgSplayIndex _fList;
static unsigned int _refCount;
static unsigned int _maxSize;
static ddgSplayKey _minNode;
static ddgSplayKey _maxNode;
ddgSplayIndex _nullNode;
ddgSplayIndex _header;
unsigned int _size;
static unsigned int _totalSize;
ddgSplayIndex ddgSplay( ddgSplayKey Item, ddgSplayIndex n );
ddgSplayIndex SingleRotateWithLeft( ddgSplayIndex n );
ddgSplayIndex SingleRotateWithRight( ddgSplayIndex n );
public:
ddgSplayTree(void);
~ddgSplayTree(void);
ddgSplayIndex clear( ddgSplayIndex n );
inline ddgSplayIndex find( ddgSplayKey k, ddgSplayIndex n )
{ return ddgSplay( k, n ); }
inline ddgSplayIndex findMin( ddgSplayIndex n );
inline ddgSplayIndex findMax( ddgSplayIndex n );
ddgSplayIndex insert( ddgSplayKey k, ddgSplayIndex n );
ddgSplayIndex remove( ddgSplayKey k, ddgSplayIndex n );
private:
ddgSplayIndex _root;
public:
inline void clear( void ) { _root = clear(_root); }
inline void find( ddgSplayKey ti ) { _root = find(ti,_root); }
inline void findMin( void ) { _root = findMin(_root); }
inline void findMax( void ) { _root = findMax(_root); }
inline void insert( ddgSplayKey k ) { _root = insert(k,_root); }
inline void remove( ddgSplayKey k ) { _root = remove(k,_root); }
inline void insert( unsigned int tree, unsigned int tindex, unsigned int priority )
{ _root = insert(ddgSplayKey(tree,tindex,priority),_root); }
inline void remove( unsigned int tree, unsigned int tindex, unsigned int priority )
{ _root = remove(ddgSplayKey(tree,tindex,priority),_root); }
inline ddgSplayIndex root(void) { return _root; }
inline ddgSplayKey * retrieve(void) { return &(_root->_key); }
inline void data(ddgSplayKey k ) { _root->set(k); }
inline ddgSplayIndex left(ddgSplayIndex si)
{ return si->_left; }
inline ddgSplayIndex right(ddgSplayIndex si)
{ return si->_right; }
inline void left(ddgSplayIndex si, ddgSplayIndex sil)
{ si->_left = sil; }
inline void right(ddgSplayIndex si, ddgSplayIndex sir)
{ si->_right = sir; }
inline ddgSplayKey key(ddgSplayIndex si)
{ return si->_key; }
inline void key(ddgSplayIndex si, ddgSplayKey sk)
{ si->_key.set(sk); }
inline ddgSplayKey * retrieve(ddgSplayIndex si)
{ return &(si->_key); }
inline void data(ddgSplayKey k, ddgSplayIndex si )
{ si->set(k); }
ddgSplayIndex allocNode(void);
void freeNode(ddgSplayIndex n);
unsigned int size(void);
inline ddgSplayIndex null(void) { return _nullNode; }
inline bool isnull(ddgSplayIndex n) { return _nullNode == n; }
#ifdef _DEBUG
int printTree( ddgSplayIndex n );
#endif
};
class WEXP ddgSplayIterator
{
#define stackMax 10000
ddgSplayTree *_ddgSplaytree;
ddgSplayIndex _stack[stackMax];
ddgSplayIndex _current;
unsigned int _depth;
#ifdef _DEBUG
unsigned int _maxDepth;
#endif
public:
void reset(bool reverse = false)
{
#ifdef _DEBUG
_maxDepth = 0;
#endif
_depth = 0;
_current = _ddgSplaytree->root();
// find smallest (leftmost) or largest (rightmost) entry.
while (_current != _ddgSplaytree->null()) {
ddgAsserts(_depth < stackMax, "ddgSplay Iterator ran out of stack space");
#ifdef _DEBUG
if (_depth > _maxDepth) _maxDepth = _depth;
#endif
_stack[_depth] = _current;
_depth++;
_current = reverse ? _ddgSplaytree->right(_current) : _ddgSplaytree->left(_current);
}
if (_depth)
{
_depth--;
_current = _stack[_depth];
}
}
ddgSplayIterator( ddgSplayTree *st, bool reverse = false)
{
_ddgSplaytree = st;
reset(reverse);
}
inline void next(void)
{
if (_current != _ddgSplaytree->null())
{
_current = _ddgSplaytree->right(_current);
while (true)
{ // we'll use break to exit the loop
// If there is a left child, go to it.
if (_current != _ddgSplaytree->null())
{
ddgAsserts(_depth < stackMax, "ddgSplay Iterator ran out of stack space");
#ifdef _DEBUG
if (_depth > _maxDepth) _maxDepth = _depth;
#endif
_stack[_depth] = _current;
_depth++;
_current = _ddgSplaytree->left(_current);
}
else
{ // backtrack
if (_depth)
{
_depth--;
_current = _stack[_depth];
break;
}
else // stack is empty; done
{
_current = _ddgSplaytree->null();
break;
}
}
}
}
}
inline void prev(void)
{
if (_current != _ddgSplaytree->null())
{
_current = _ddgSplaytree->left(_current);
while (true)
{ // we'll use break to exit the loop
// If there is a right child, go to it.
if (_current != _ddgSplaytree->null())
{
ddgAsserts(_depth < stackMax, "ddgSplay Iterator ran out of stack space");
#ifdef _DEBUG
if (_depth > _maxDepth) _maxDepth = _depth;
#endif
_stack[_depth] = _current;
_depth++;
_current = _ddgSplaytree->right(_current);
}
else
{ // backtrack
if (_depth)
{
_depth--;
_current = _stack[_depth];
break;
}
else // stack is empty; done
{
_current = _ddgSplaytree->null();
break;
}
}
}
}
}
inline ddgSplayIndex current(void) { return _current; }
inline bool end(void) { return (_current == _ddgSplaytree->null()) ? true : false; }
};
#endif