#ifndef SQUID_SPLAY_H #define SQUID_SPLAY_H #ifndef __cplusplus #else #include "Stack.h" template class SplayNode { public: typedef V Value; typedef int SPLAYCMP(Value const &a, Value const &b); typedef void SPLAYFREE(Value &); typedef void SPLAYWALKEE(Value const & nodedata, void *state); static void DefaultFree (Value &aValue) {delete aValue;} SplayNode (Value const &); Value data; mutable SplayNode *left; mutable SplayNode *right; void destroy(SPLAYFREE *); void walk(SPLAYWALKEE *, void *callerState); bool empty() const { return this == NULL; } SplayNode const * start() const; SplayNode const * finish() const; SplayNode * remove(const Value data, SPLAYCMP * compare); SplayNode * insert(Value data, SPLAYCMP * compare); template SplayNode * splay(const FindValue &data, int( * compare)(FindValue const &a, Value const &b)) const; }; typedef SplayNode splayNode; template class SplayConstIterator; template class SplayIterator; template class Splay { public: typedef V Value; typedef int SPLAYCMP(Value const &a, Value const &b); typedef void SPLAYFREE(Value &); typedef SplayIterator iterator; typedef const SplayConstIterator const_iterator; Splay():head(NULL), elements (0) {} mutable SplayNode * head; template Value const *find (FindValue const &, int( * compare)(FindValue const &a, Value const &b)) const; void insert(Value const &, SPLAYCMP *compare); void remove(Value const &, SPLAYCMP *compare); void destroy(SPLAYFREE *); SplayNode const * start() const; SplayNode const * finish() const; size_t size() const; const_iterator begin() const; const_iterator end() const; size_t elements; }; SQUIDCEXTERN int splayLastResult; SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, splayNode::SPLAYCMP *); SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, splayNode::SPLAYCMP *); SQUIDCEXTERN splayNode *splay_splay(const void **, splayNode *, splayNode::SPLAYCMP *); SQUIDCEXTERN void splay_destroy(splayNode *, splayNode::SPLAYFREE *); SQUIDCEXTERN void splay_walk(splayNode *, splayNode::SPLAYWALKEE *, void *callerState); /* inline methods */ template SplayNode::SplayNode (Value const &someData) : data(someData), left(NULL), right (NULL) {} template void SplayNode::walk(SPLAYWALKEE * walkee, void *state) { if (this == NULL) return; if (left) left->walk(walkee, state); walkee(data, state); if (right) right->walk(walkee, state); } template SplayNode const * SplayNode::start() const { if (this && left) return left->start(); return this; } template SplayNode const * SplayNode::finish() const { if (this && right) return right->finish(); return this; } template void SplayNode::destroy(SPLAYFREE * free_func) { if (!this) return; if (left) left->destroy(free_func); if (right) right->destroy(free_func); free_func(data); delete this; } template SplayNode * SplayNode::remove(Value const dataToRemove, SPLAYCMP * compare) { if (this == NULL) return NULL; SplayNode *result = splay(dataToRemove, compare); if (splayLastResult == 0) { /* found it */ SplayNode *newTop; if (result->left == NULL) { newTop = result->right; } else { newTop = result->left->splay(dataToRemove, compare); /* temporary */ newTop->right = result->right; result->right = NULL; } delete result; return newTop; } return result; /* It wasn't there */ } template SplayNode * SplayNode::insert(Value dataToInsert, SPLAYCMP * compare) { /* create node to insert */ SplayNode *newNode = new SplayNode(dataToInsert); if (this == NULL) { splayLastResult = -1; newNode->left = newNode->right = NULL; return newNode; } SplayNode *newTop = splay(dataToInsert, compare); if (splayLastResult < 0) { newNode->left = newTop->left; newNode->right = newTop; newTop->left = NULL; return newNode; } else if (splayLastResult > 0) { newNode->right = newTop->right; newNode->left = newTop; newTop->right = NULL; return newNode; } else { /* duplicate entry */ delete newNode; return newTop; } } template template SplayNode * SplayNode::splay(FindValue const &dataToFind, int( * compare)(FindValue const &a, Value const &b)) const { if (this == NULL) { /* can't have compared successfully :} */ splayLastResult = -1; return NULL; } Value temp = Value(); SplayNode N(temp); SplayNode *l; SplayNode *r; SplayNode *y; N.left = N.right = NULL; l = r = &N; SplayNode *top = const_cast *>(this); for (;;) { splayLastResult = compare(dataToFind, top->data); if (splayLastResult < 0) { if (top->left == NULL) break; if ((splayLastResult = compare(dataToFind, top->left->data)) < 0) { y = top->left; /* rotate right */ top->left = y->right; y->right = top; top = y; if (top->left == NULL) break; } r->left = top; /* link right */ r = top; top = top->left; } else if (splayLastResult > 0) { if (top->right == NULL) break; if ((splayLastResult = compare(dataToFind, top->right->data)) > 0) { y = top->right; /* rotate left */ top->right = y->left; y->left = top; top = y; if (top->right == NULL) break; } l->right = top; /* link left */ l = top; top = top->right; } else { break; } } l->right = top->left; /* assemble */ r->left = top->right; top->left = N.right; top->right = N.left; return top; } template template typename Splay::Value const * Splay::find (FindValue const &value, int( * compare)(FindValue const &a, Value const &b)) const { head = head->splay(value, compare); if (splayLastResult != 0) return NULL; return &head->data; } template void Splay::insert(Value const &value, SPLAYCMP *compare) { assert (!find (value, compare)); head = head->insert(value, compare); ++elements; } template void Splay::remove(Value const &value, SPLAYCMP *compare) { assert (find (value, compare)); head = head->remove(value, compare); --elements; } template SplayNode const * Splay:: start() const { if (head) return head->start(); return NULL; } template SplayNode const * Splay:: finish() const { if (head) return head->finish(); return NULL; } template void Splay:: destroy(SPLAYFREE *free_func) { if (head) head->destroy(free_func); head = NULL; elements = 0; } template size_t Splay::size() const { return elements; } template const SplayConstIterator Splay::begin() const { return const_iterator(head); } template const SplayConstIterator Splay::end() const { return const_iterator(NULL); } template class SplayConstIterator { public: typedef const V value_type; SplayConstIterator (SplayNode *aNode); bool operator == (SplayConstIterator const &right) const; SplayConstIterator operator ++ (int dummy); SplayConstIterator &operator ++ (); V const & operator * () const; private: void advance(); void addLeftPath(SplayNode *aNode); void init(SplayNode *); Stack *> toVisit; }; template SplayConstIterator::SplayConstIterator (SplayNode *aNode) { init(aNode); } template bool SplayConstIterator::operator == (SplayConstIterator const &right) const { return toVisit.top() == right.toVisit.top(); } template SplayConstIterator & SplayConstIterator::operator ++ () { advance(); return *this; } template SplayConstIterator SplayConstIterator::operator ++ (int dummy) { SplayConstIterator result = *this; advance(); return result; } /* advance is simple enough: * if the stack is empty, we're done. * otherwise, pop the last visited node * then, pop the next node to visit * if that has a right child, add it and it's * left-to-end path. * then add the node back. */ template void SplayConstIterator::advance() { if (toVisit.size() == 0) return; toVisit.pop(); if (toVisit.size() == 0) return; SplayNode *currentNode = toVisit.pop(); addLeftPath(currentNode->right); toVisit.push_back(currentNode); } template void SplayConstIterator::addLeftPath(SplayNode *aNode) { if (aNode == NULL) return; do { toVisit.push_back(aNode); aNode = aNode->left; } while (aNode != NULL); } template void SplayConstIterator::init(SplayNode *head) { addLeftPath(head); } template V const & SplayConstIterator::operator * () const { /* can't dereference when past the end */ if (toVisit.size() == 0) fatal ("Attempt to dereference SplayConstIterator past-the-end\n"); return toVisit.top()->data; } #endif /* cplusplus */ #endif /* SQUID_SPLAY_H */