/* 0 An AVL Tree class This file contains the implementation of a standard AVL tree. Additionally some specialized functions are provided. //[_] [\_] */ #ifndef AVLTREE_H #define AVLTREE_H /* #define __AVL_TRACE__ cout << __FILE__ << "@" << __LINE__ << ":" << \ __PRETTY_FUNCTION__ << endl; */ //#define __AVL_TRACE__ cout << __FUNCTION__ << endl; #define __AVL_TRACE__ #include #include #include #include template class unary_functor{ public: virtual result operator()(const arg& a) const = 0; virtual ~unary_functor(){} }; template class StdComp{ public: static bool smaller(const Obj& o1, const Obj& o2){ return o1 < o2; } static bool equal(const Obj& o1, const Obj& o2){ return o1 == o2; } static bool greater(const Obj& o1, const Obj& o2){ return o1 > o2; } }; namespace avltree{ /* 0 Forward declaration of the AVLTree class */ template > class AVLTree; /* 1 class Node This class represents a single node of an AVL tree. */ template class AvlNode{ friend class AVLTree; public: /* 1.0 Constructor This constructor creates a new leaf with the given content. */ AvlNode(const contenttype& content1): content(content1),left(0), right(0),height(0){ __AVL_TRACE__ } /* 1.0 Copy constructor Creates a depth copy of this node. */ AvlNode(const AvlNode& source): content(source.content), left(0), right(0),height(source.height){ __AVL_TRACE__ this->left = source.left==NULL?NULL:new AvlNode(*source.left); this->right = source.right==NULL?NULL:new AvlNode(*source.right); } /* 1.0 Assignment Operator */ AvlNode& operator=( const AvlNode& source){ __AVL_TRACE__ this->content = source.content; this->left = source.left ? new AvlNode(source.left) :NULL; this->right = source.right ? new AvlNode(source.right) :NULL; this->heigth = source.height; return *this; } /* 1.0 Destructor Deletes the subtree represented by this tree. */ ~AvlNode(){ __AVL_TRACE__ if(left) delete left; if(right) delete right; left = NULL; right = NULL; } /* 1.1 Cut Sets the left and the right son of this node to NULL without deleting them. This can be useful in deleting a single node but keeping the subtrees in the memory */ void cut(){ __AVL_TRACE__ this->left = NULL; this->right = NULL; } /* 1.1 getLeftSon returns the left subtree */ AvlNode* getLeftSon()const{ __AVL_TRACE__ return left; } /* 1.1 getRightSon Returns the right subtree. */ AvlNode* getRightSon()const{ __AVL_TRACE__ return right; } /* 1.1 balance Computes the balance of this node. */ int balance()const{ __AVL_TRACE__ int h1 = left?left->height+1:0; int h2 = right?right->height+1:0; return h1-h2; } /* 1.1 updateHeight Computes the height of this node from the height of the sons. This method should be called whenever the sons are changed. Note that only the direct descendants are used to compute the new height. */ void updateHeight(){ __AVL_TRACE__ int h1 = left==NULL?0:left->height+1; int h2 = right==NULL?0:right->height+1; height = std::max(h1,h2); } /* 1.1 isLeaf Returns true when this node have no sons */ bool isLeaf()const{ __AVL_TRACE__ return left==NULL && right==NULL; } contenttype* getContent() { return &content; } AvlNode* clone(){ AvlNode* res; res = new AvlNode(content); if(this->left){ res->left = this->left->clone(); } if(this->right){ res->right = this->right->clone(); } res->height = this->height; return res; } private: /* 1.2 Data Members */ contenttype content; AvlNode* left; AvlNode* right; int height; // required for the balance computation }; /* 2 AVL Tree This class provides an AVL Tree. */ template class AVLTree{ public: typedef AvlNode Node; /* 2.1 Constructor Creates an empty avl tree. */ AVLTree(){ __AVL_TRACE__ root = NULL; } /* 2.2 Empty Removes all entries from the tree. */ void Empty(){ if(root){ delete root; } root=NULL; } AVLTree* clone() { AVLTree* res = new AVLTree(); if(root){ res->root = root->clone(); } return res; } void destroy( void (*kill)(contenttype&)){ if(root){ destroy(root, kill); delete root; root = NULL; } } static void destroy(Node* root, void (*kill)(contenttype&)){ if(root->left){ destroy(root->left,kill); delete root->left; root->left = 0; } if(root->right){ destroy(root->right,kill); delete root->right; root->right=0; } kill(root->content); } /* 2.2 Copy Constructor Creates a depth copy of the argument. */ AVLTree(const AVLTree& T){ __AVL_TRACE__ if(T.root==NULL) root = NULL; else root = new Node(*T.root); } /* 2.3 Destructor */ ~AVLTree(){ __AVL_TRACE__ if(root){ delete root; root = NULL; } } /* 2.4 Assignment operator */ AVLTree& operator=( const AVLTree source){ __AVL_TRACE__ if(root){ delete root; } root = source.root ? new Node(source.root) : NULL; return *this; } /* 2.5 Check for emptyness */ bool IsEmpty()const{ __AVL_TRACE__ return root==NULL; } /* 2.6 Number of Elements */ int Size() const{ __AVL_TRACE__ return Size(root); } /* 2.7 Height of the tree */ int GetHeight() const{ __AVL_TRACE__ return root->height; } /* 2.8 check This function is for debugging only. Error messages are written to out. */ bool Check(std::ostream& out)const{ return Check(root,out); } /* 2.1 Insert Inserts an object into this tree. */ bool insert(const contenttype& x){ __AVL_TRACE__ bool success; root = insert(root,x,success); root->updateHeight(); return success; } /* 2.1 insertN This insert functions inserts the element provided as first parameter into the tree. The other parameters are set to the direct neighbour in the tree. This means __left__ points to the greatest element in the tree which is smaller than __x__ and __right__ points to the smallest element in the tree greater than __x__. If such element(s) not exist(s), the corresponding parameter is set to 0. */ bool insertN(const contenttype& x, // in contenttype*& left, // out contenttype*& right){ // out __AVL_TRACE__ bool success; left = 0; right = 0; root = insertN(root,x,success,left,right); root->updateHeight(); return success; } /* ~insert2~ inserts x into the tree and returns a pointer to the stored element. If x is already an element of the tree, a pointer to the stored element is returned. */ contenttype* insert2(const contenttype& x){ __AVL_TRACE__ contenttype* result=0; bool dummy; root = insert2(root,x, result, dummy); root->updateHeight(); return result; } contenttype* insert3(const contenttype& x, bool& found){ __AVL_TRACE__ contenttype* result=0; root = insert2(root,x, result, found); root->updateHeight(); return result; } /* 2.2 remove Deletes __x__ from the tree. if found, x is set to the current entry in the tree */ bool remove(contenttype& x){ __AVL_TRACE__ bool found = false; root = remove(root,x,found); if(root!=NULL){ root->updateHeight(); } return found; } /* 2.3 remove[_]smallest Removes the smallest object stored in the tree fulfilling the given predicate. The return value indicates whether such an entry is found within the tree. The runtime of this operation is linearly to the count of entries within the tree. */ bool remove_smallest(const unary_functor& pred){ __AVL_TRACE__ bool found = false; root = remove_smallest(root,pred,found); if(root!=NULL){ root->updateHeight(); } return found; } /* 2.4 removeAll Calls removes smallest until no object fulfills the given condition. The return values is the number of deleted entries. */ unsigned int removeAll(const unary_functor& pred){ unsigned int count = 0; while(remove_smallest(pred)) { count++; } return count; } /* 2.1 removeN Deletes __x__ from the tree. __left__ and __right__ are set to the neighbours __x__ in the tree. If the neighbours not exist or __x__ is not an element of the tree, the corresponding parameter is set to be NULL. */ bool removeN(const contenttype& x, contenttype*& left, contenttype*& right){ __AVL_TRACE__ bool found = false; left = 0; right = 0; root = removeN(root,x,found,left,right); if(root){ root->updateHeight(); } return found; } /* 2.3 member Checks whether __x__ is contained in the tree. */ bool member(const contenttype& x) const{ __AVL_TRACE__ return member(root,x); } contenttype* getMember(const contenttype& x) const{ __AVL_TRACE__ return getMember(root,x); } /* ~GetMember~ Returns a pointer to the entry ~m~ in the tree for which ~x~==~m~ holds. If the element is not found, the return value is NULL. After calling this function ~left~ and ~right~ points to the element stored in the tree which is the left and right neighbour of x respectively. If a neighbour don't exist, the corresponding parameter is set to NULL. */ contenttype* getMember(contenttype& x, contenttype*& left, contenttype*& right){ __AVL_TRACE__ left = 0; right = 0; return getMember(root,x,left,right); } /* 2.4 GetNearestSmallerOrEqual This function returns a pointer to the biggest object store din the tree which is smaller or equal to __pattern__. */ contenttype const * GetNearestSmallerOrEqual(const contenttype& pattern)const { __AVL_TRACE__ return GetNearestSmallerOrEqual(root,pattern); } /* 2.5 GetNearestGreaterOrEqual This function works similar to the GetNearestSmaller function but returns the nearest entry to pattern which is greater or equal to it. */ contenttype const* GetNearestGreaterOrEqual(const contenttype& pattern)const{ __AVL_TRACE__ return GetNearestGreaterOrEqual(root,pattern); } /* 2.6 GetMin This function returns the minimum value stored in the tree. If the tree is empty, NULL is returned. */ contenttype const* GetMin()const{ __AVL_TRACE__ return GetMin(root); } /* 2.8 GetMax This returns a pointer to the maximum value stored in the tree or NULL if the tree is empty. */ contenttype const* GetMax()const{ __AVL_TRACE__ return GetMax(root); } /* 2.9 GetNearestSmaller Returns a pointer to the biggest entry in the tree which is smaller than the argument or NULL if there is no such object. */ contenttype const* GetNearestSmaller(const contenttype& pattern) const{ __AVL_TRACE__ return GetNearestSmaller(root,pattern); } /* 2.10 GetNearestGreater This function works symmetrically to the ~GetNearestSmaller~ function. */ contenttype const* GetNearestGreater(const contenttype& pattern) const{ __AVL_TRACE__ return GetNearestGreater(root,pattern); } /* ~print~ Prints this tree to the give ostream. The format is understand by the tree viewer of Secondo's Javagui. */ void Print(std::ostream& out)const{ out << "( tree (" << endl; Print(root, out); out << "))" << endl; } class iterator; /* ~begin~ This function returns an iterator over this tree. */ iterator begin(){ iterator it(root); return it; } /* ~tail~ This function creates an iterator which is positioned to the fisrt element within the tree which is equals to or greater than the given minimum. */ iterator tail(contenttype min){ iterator it(root,min); return it; } /* ~iterator~ This inner class provides an iterator for sorted iterating trough the tree. */ class iterator{ public: iterator():thestack(){} iterator(const iterator& it):thestack(it.thestack){ __AVL_TRACE__ } iterator& operator=(const iterator& it){ __AVL_TRACE__ this->thestack = it.thestack; return *this; } /* ~Get~ The ~Get~ function returns the value currently under this iterator. */ contenttype* Get() const{ __AVL_TRACE__ if(thestack.empty()){ return 0; } else { Node* elem = thestack.top(); return (elem->getContent()); } } /* ~Next~ The ~Next~ function sets the iterator to the next element. If no more elements are available, the result will be __false__ otherwise __true__. */ bool Next(){ __AVL_TRACE__ if(thestack.empty()){ return false; } const Node* elem = thestack.top(); Node* son; if( (son = elem->getRightSon())){ thestack.pop(); // the current node is processed thestack.push(son); while((son = son->getLeftSon())){ thestack.push(son); } return true; } else { // there is no right son thestack.pop(); return !thestack.empty(); } } /* ~Constructor~ Creates an iterator for the given tree. The position is set to the smallest entry in the tree. */ iterator(Node* root){ __AVL_TRACE__ Node* son = root; while(son){ thestack.push(son); son = son->getLeftSon(); } } /* ~Contructor~ Creates a new iterator for root. The position is set to the first entry within the tree which is equals to or greater than min. */ iterator(Node* root, const contenttype min){ __AVL_TRACE__ if(root){ tail(root,min); } } /* ~Increment operator~ This operator sets this iterator to the next position in the tree. */ iterator& operator++(int){ __AVL_TRACE__ Next(); return *this; } /* ~Dereference operator~ This operator returns the element currently under the iterator's cursor. If no more elements exist, NULL is returned. */ const contenttype* operator*(){ __AVL_TRACE__ return Get(); } /* ~hasNext~ This function checks whether after the current element further elements exist. */ bool hasNext(){ __AVL_TRACE__ int size = thestack.size(); if(size==0){ // no elements return false; } if(size>1){ return true; } return (thestack.top()->getRightSon()!=0); } /* ~onEnd~ The ~onEnd~ function checks whether the iterator does not have any elements, i.e. whether Get or [*] would return NULL. */ bool onEnd(){ return thestack.empty(); } private: /* ~Data member~ We manage stack to be able to go up in the tree. */ std::stack thestack; /* ~tail~ This function support the contructor having a mimimum argument. */ Node* tail( Node* root, const contenttype& min){ __AVL_TRACE__ assert(root); if(Comparator::equal(root->content,min)){ thestack.push(root); return root; } else if(Comparator::smaller(root->content , min)){ // root.content < min // may be in the right subtree there is the node // searched for Node* son = root->getRightSon(); if(!son){ return 0; } else { return tail(son,min); } } else { // root.content > min // may be within the left subtree there is a better // node thestack.push(root); Node* son = root->getLeftSon(); if(son){ Node* best = tail(son,min); return best?best:root; } else { return 0; } } } }; private: void Print(const Node* root, std::ostream& out)const{ if(!root){ out << " '' "; return; } out << "'"<content <<"'"; out << "("; Print(root->getLeftSon(),out); out << ")"; out << "("; Print(root->getRightSon(),out); out << ")"; } /* 2.11 rotateRight Rotates a node right and returns the new root. Note there is no check wether the sons required for this operations exists */ static Node* rotateRight( Node* root){ __AVL_TRACE__ Node* y = root->left; Node* B = y->right; Node* C = root->right; root->left=B; root->right=C; root->updateHeight(); y->right=root; y->updateHeight(); return y; } /* 2.1 rotateLeftRight Performs a left right double rotation around root */ static Node* rotateLeftRight( Node* root){ __AVL_TRACE__ Node* x = root; Node* z = root->left; Node* y = z->right; Node* A = z->left; Node* B = y->left; Node* C = y->right; z->left=A; z->right=B; z->updateHeight(); x->left=C; x->updateHeight(); y->left=z; y->right=x; y->updateHeight(); return y; } /* 2.1 rotateLeft Performs a left rotation around root. */ static Node* rotateLeft( Node* root){ __AVL_TRACE__ Node* y = root->right; Node* B = y->left; root->right = B; root->updateHeight(); y->left=root; y->updateHeight(); return y; } /* 2.1 rotateRightLeft performs a right left double rotation around root */ static Node* rotateRightLeft( Node* root){ __AVL_TRACE__ Node* x = root; Node* z = x->right; Node* y = z->left; Node* B1 = y->left; Node* B2 = y->right; x->right=B1; x->updateHeight(); z->left = B2; z->updateHeight(); y->left = x; y->right=z; y->updateHeight(); return y; } /* 2.1 insert This function inserts __content__ into the subtree given by root. It returns the root of the new tree. */ static Node* insert( Node* root, const contenttype& content,bool& success){ __AVL_TRACE__ if(root==NULL){ // leaf reached success=true; return new Node(content); } contenttype c = root->content; if(Comparator::equal(c,content)){ //an AVL tree represents a set, do nothing success=false; return root; } else if(Comparator::smaller(content,c)){ // perform the left subtree root->left = insert(root->left,content,success); root->updateHeight(); if(abs(root->balance())>1){ // rotation or double rotation required // check where the overhang is if(root->left->balance()>0){ // single rotation is sufficient return rotateRight(root); } if(root->left->balance()<0){ return rotateLeftRight(root); } assert(false); // should never be reached return NULL; } else{ // root remains balanced return root; } } else{ // content > c => insert at right root->right = insert(root->right,content,success); root->updateHeight(); if(abs(root->balance())>1){ if(root->right->balance()<0){ // LeftRotation return rotateLeft(root); } if(root->right->balance()>0){ return rotateRightLeft(root); } assert(false); // should never be reached return NULL; } else{ // no rotation required return root; } } } /* 2.1 insertN This function inserts __content__ into the subtree given by root. It returns the root of the new tree. Left and right are set to the left (right) neighbour of the new element (or NULL) if there are not present. __left__ and __right__ must be initialized with 0 to ensure a correct result for them. */ static Node* insertN( Node* root, const contenttype& content,bool& success, contenttype*& left, contenttype*& right){ __AVL_TRACE__ if(root==NULL){ // leaf reached success=true; return new Node(content); } contenttype c = root->content; if(Comparator::equal(c,content)){// an AVL tree represents a set, do nothing // set the neighbours if(root->left){ Node* tmp = root->left; while(tmp->right){ tmp = tmp->right; } left = &tmp->content; } if(root->right){ Node* tmp = root->right; while(tmp->left){ tmp = tmp->left; } right = &tmp->content; } success=false; return root; } else if(Comparator::smaller(content,c)){ // perform the left subtree root->left = insertN(root->left,content,success,left,right); if(!right){ right = &root->content; } if(!left && Comparator::smaller(root->content,content)){ left = &root->content; } root->updateHeight(); if(abs(root->balance())>1){ // rotation or double rotation required // check where the overhang is if(root->left->balance()>0){ // single rotation is sufficient return rotateRight(root); } if(root->left->balance()<0){ return rotateLeftRight(root); } assert(false); // should never be reached return NULL; } else{ // root remains balanced return root; } } else{ // content > c => insert at right root->right = insertN(root->right,content,success,left,right); if(!left){ left = &root->content; } if(!right && Comparator::smaller(content,root->content)){ right = &root->content; } root->updateHeight(); if(abs(root->balance())>1){ if(root->right->balance()<0){ // LeftRotation return rotateLeft(root); } if(root->right->balance()>0){ return rotateRightLeft(root); } assert(false); // should never be reached return NULL; } else{ // no rotation required return root; } } } static Node* insert2(Node* root, const contenttype& content, contenttype *& elem, bool& found){ __AVL_TRACE__ if(root==NULL){ // leaf reached Node* res = new Node(content); elem = &res->content; found = false; return res; } contenttype c = root->content; if(Comparator::equal(c,content)){ //an AVL tree represents a set, do nothing elem = &root->content; found = true; return root; } else if(Comparator::smaller(content,c)){ // perform the left subtree root->left = insert2(root->left,content,elem, found); root->updateHeight(); if(abs(root->balance())>1){ // rotation or double rotation required // check where the overhang is if(root->left->balance()>0){ // single rotation is sufficient return rotateRight(root); } if(root->left->balance()<0){ return rotateLeftRight(root); } assert(false); // should never be reached return NULL; } else{ // root remains balanced return root; } } else{ // content > c => insert at right root->right = insert2(root->right,content,elem,found); root->updateHeight(); if(abs(root->balance())>1){ if(root->right->balance()<0){ // LeftRotation return rotateLeft(root); } if(root->right->balance()>0){ return rotateRightLeft(root); } assert(false); // should never be reached return NULL; } else{ // no rotation required return root; } } } /* 2.1 remove Deletes the Node holding the value __content__ from the subtree rooted by __root__. It returns the new root of the created tree. */ static Node* remove( Node* root, contenttype& x, bool& found){ __AVL_TRACE__ if(root==NULL){ // nothing found found = false; return NULL; } contenttype& value = root->content; if(Comparator::smaller(x,value)){ root->left = remove(root->left,x,found); if(!found){ return root; } root->updateHeight(); if(root->right==NULL){ // because we have deleted // in the left part, we cannot // get any unbalanced subtree when right is null return root; } if(abs(root->balance())>1){ // we have to rotate // we know that the height of the left son is smaller than before int RB = root->right->balance(); if(RB<=0){ // rotation is sufficient return rotateLeft(root); } else{ return rotateRightLeft(root); } } else{ // balance of root is ok return root; } assert(false); } if(Comparator::smaller(value,x)){ root->right = remove(root->right,x,found); if(!found){ return root; } root->updateHeight(); if(root->left==NULL){ return root; } if(abs(root->balance())>1){ // we have to rotate int LB = root->left->balance(); if(LB>=0){ return rotateRight(root); } else{ return rotateLeftRight(root); } } else { // root is balanced return root; } assert(false); } // value == x , value found , we have a lot to do found = true; x = root->content; if(root->isLeaf()){ delete root; // free the memory return NULL; // delete a single leaf } if(root->left==NULL){ Node* res = root->right; root->cut(); delete root; return res; } if(root->right==NULL){ Node* res = root->left; root->cut(); delete root; return res; } Node* minimum(0); root->right=deletemin(root->right,minimum); minimum->left = root->left; minimum->right = root->right; root->cut(); delete root; root = minimum; root->updateHeight(); if(abs(root->balance())>1){ // we have to rotate int LB = root->left->balance(); if(LB>=0){ return rotateRight(root); } else{ return rotateLeftRight(root); } } else{ // root is balanced return root; } assert(false); return 0; } static Node* remove_smallest( Node* root, const unary_functor& pred, bool& found){ __AVL_TRACE__ if(root==NULL || found){ // no tree or already removed found = false; return NULL; } // try to delete in the left subtree root->left = remove_smallest(root->left,pred,found); if(found) { // found the the subtree root->updateHeight(); if(root->right==NULL){ // because we have deleted // in the left part, we cannot // get any unbalanced subtree when right is null return root; } if(abs(root->balance())>1){ // we have to rotate // we know that the height of the left son is smaller than before int RB = root->right->balance(); if(RB<=0){ // rotation is sufficient return rotateLeft(root); } else{ return rotateRightLeft(root); } } else{ // balance of root is ok return root; } assert(false); } // not found, try this node found = pred(root->content); if(found){ if(root->isLeaf()){ delete root; // free the memory return NULL; // delete a single leaf } if(root->left==NULL){ Node* res = root->right; root->cut(); delete root; return res; } if(root->right==NULL){ Node* res = root->left; root->cut(); delete root; return res; } Node* minimum(0); root->right=deletemin(root->right,minimum); minimum->left = root->left; minimum->right = root->right; root->cut(); delete root; root = minimum; root->updateHeight(); if(abs(root->balance())>1){ // we have to rotate int LB = root->left->balance(); if(LB>=0){ return rotateRight(root); } else{ return rotateLeftRight(root); } } else{ // root is balanced return root; } assert(false); } root->right = remove_smallest(root->right,pred,found); if(found){ root->updateHeight(); if(root->left==NULL){ return root; } if(abs(root->balance())>1){ // we have to rotate int LB = root->left->balance(); if(LB>=0){ return rotateRight(root); } else{ return rotateLeftRight(root); } } else { // root is balanced return root; } assert(false); } // predicate could not be evaluated to true in the subtree // represented by root // keep tree unchanged assert(!found); return root; } /* 2.1 removeN Deletes the Node holding the value __content__ from the subtree rooted by __root__. Set the arguments __left__ and __right__ to the left and right neighbour respectively. __left__ and __right__ have to be initialized with NULL. It returns the new root of the created tree. */ static Node* removeN( Node* root, const contenttype& x, bool& found, contenttype*& left, contenttype*& right){ __AVL_TRACE__ if(root==NULL){ // nothing found found = false; return NULL; } contenttype value = root->content; if(Comparator::smaller(x,value)){ root->left = removeN(root->left,x,found,left,right); if(!right){ right = &root->content; } if(!left && Comparator::smaller(value , x)){ left = &root->content; } root->updateHeight(); if(root->right==NULL){ // because we have deleted // in the left part, we cannot // get any unbalanced subtree when right is null return root; } if(abs(root->balance())>1){ // we have to rotate // we know that the height of the left son is smaller than before int RB = root->right->balance(); if(RB<=0){ // rotation is sufficient return rotateLeft(root); } else{ return rotateRightLeft(root); } } else{ // balance of root is ok return root; } } else if(Comparator::smaller(value,x)){ root->right = removeN(root->right,x,found,left,right); if(!left){ left = &root->content; } if(!right && Comparator::smaller(x,value)){ right = &root->content; } root->updateHeight(); if(abs(root->balance())>1){ // we have to rotate int LB = root->left->balance(); if(LB>=0){ return rotateRight(root); } else{ return rotateLeftRight(root); } } else { // root is balanced return root; } } else { // value == x , value found , we have a lot to do found = true; if(root->isLeaf()){ delete root; // free the memory return NULL; // delete a single leaf } if(root->left==NULL){ // search the content of the right neighbour Node* r = root->right; while(r->left){ r = r->left; } right = &r->content; Node* res = root->right; root->cut(); delete root; return res; } if(root->right==NULL){ // search for the left neighbour Node* l = root->left; while(l->right){ l = l->right; } left = &l->content; Node* res = root->left; root->cut(); delete root; return res; } // both sons exist Node* tmp; tmp = root->left; assert(tmp); while(tmp->right){ tmp = tmp->right; } left = &tmp->content; Node* minimum(0); root->right=deletemin(root->right,minimum); minimum->left = root->left; minimum->right = root->right; root->cut(); delete root; root = minimum; root->updateHeight(); right = &root->content; if(abs(root->balance())>1){ // we have to rotate int LB = root->left->balance(); if(LB>=0){ return rotateRight(root); } else{ return rotateLeftRight(root); } } else{ // root is balanced return root; } } } /* 2.1 deleteMin Removes the node containing the minimum of the subtree stored in root. The node itself is not deleted. The minimum is returned in the appropriate parameter. The left and right pointer of mininum a set to be null. **/ static Node* deletemin( Node* root, Node*& minimum){ __AVL_TRACE__ if(root->left==NULL){ // this node is to remove Node* res = root->right; root->cut(); minimum = root; // save the value return res; } else{ // try to delete more left root->left=deletemin(root->left,minimum); root->updateHeight(); if(!root->right){ return root; } if(abs(root->balance())>1){ // we have to rotate int RB = root->right->balance(); if(RB<=0){ // rotation is sufficient return rotateLeft(root); } else{ return rotateRightLeft(root); } } else{ return root; } } assert(false); return 0; } /* 2.1 Member Checks whether x is contained in the subtree given by __root__. */ static bool member(Node const* const root, const contenttype& content){ __AVL_TRACE__ if(root==NULL) return false; if(Comparator::equal(root->content,content)) return true; return Comparator::smaller(content,root->content) ? member(root->left,content) : member(root->right,content); } static contenttype* getMember( Node* root, const contenttype& content){ __AVL_TRACE__ Node* current = root; while(current && !( Comparator::equal(current->content,content))){ if(Comparator::smaller(content , current->content)){ current = current->left; } else { current = current->right; } } if(!current){ // content not found return 0; } else { return ¤t->content; } } static contenttype* getMember( Node* root, contenttype& x, contenttype*& left, contenttype*& right){ __AVL_TRACE__ if(root==NULL) return 0; // member not found if(Comparator::equal(root->content,x)){ if(root->left){ // search the left neighbour Node* tmp = root->left; while(tmp->right){ tmp = tmp->right; } left = &tmp->content; } if(root->right){ // search the right neighbour Node* tmp = root->right; while(tmp->left){ tmp = tmp->left; } right = &tmp->content; } return &root->content; } if(Comparator::smaller(x , root->content)){ contenttype* res = getMember(root->left,x,left,right); if(!right){ right = &root->content; } return res; } else { // x > root->content contenttype* res = getMember(root->right,x,left,right); if(!left){ left = &root->content; } return res; } } /* 2.1 Check */ static bool Check(Node const* const root, std::ostream& out) { if(!root){ return true; } else { if(!Check(root->left,out)){ return false; } if(!Check(root->right,out)){ return false; } // check whether height is correct int h1 = root->left?root->left->height + 1:0; int h2 = root->right?root->right->height +1:0; int h = h1>h2?h1:h2; if(!h==root->height){ out << "height not correct"; return false; } // check for balance int diff = h1>h2?h1-h2:h2-h1; if(diff>1){ out << "Balance is not correct h1 = " << h1 << ", h2 = " << h2; return false; } return CheckCmp(root->left,root->content,true,out) && CheckCmp(root->right,root->content,false,out); } } /* 2.1 CheckCmp */ static bool CheckCmp(Node const* const root, const contenttype& content, bool smaller, std::ostream& out){ if(!root){ return true; } // check the sons if(smaller){ if(! ( Comparator::smaller(root->content , content))){ cout << root->content << endl <<" is located in the left subtree of " << endl << content << " but it's not smaller" << endl; return false; } } else { if(! (Comparator::smaller(content , root->content))){ cout << root->content << endl <<" is located in the right subtree of " << endl << content << " but it's not greater" << endl; return false; } } // check the subtrees if(!CheckCmp(root->left, content, smaller, out)){ return false; } if(!CheckCmp(root->right, content, smaller, out)){ return false; } // do the check for the root node return CheckCmp(root->left,root->content,true,out) && CheckCmp(root->right,root->content,false,out); } /* 2.1 GetNearestSmallerOrEqual Returns a pointer to the biggest object stored in the tree which is smaller or equal to __pattern__. If there is noc such object, NULL is returned. */ static contenttype const* GetNearestSmallerOrEqual( Node const* const root, const contenttype& pattern) { __AVL_TRACE__ if(root==NULL) return NULL; contenttype value = root->content; if(Comparator::equal(value,pattern)){ // the nearest is equal to the pattern return &root->content; } if(Comparator::smaller(pattern, value)){ // a value smaller than pattern can only found // in the left subtree return GetNearestSmallerOrEqual(root->left,pattern); } // at this point holds value < pattern // root is a candidate for the result but possible we // can find an entry clooser to pattern in th right subtree contenttype const* tmp = GetNearestSmallerOrEqual(root->right,pattern); if(tmp){ // found an closer entry return tmp; } else{ // all entries are greater than pattern return &root->content; } } /* 2.1 GetNearestGreaterOrEqual The symmetric function to ~GetSmallerOrEqual~. */ static contenttype const* GetNearestGreaterOrEqual( Node const* const root, const contenttype& pattern) { __AVL_TRACE__ if(root==NULL) return NULL; contenttype value = root->content; if(Comparator::equal(value,pattern)){ return &root->content; } if(Comparator::smaller(pattern, value)){ // search for a closer object in the left subtree contenttype const* tmp = GetNearestGreaterOrEqual(root->left,pattern); if(tmp){ return tmp; } else{ return &root->content; } } // up to now we are smaller -> search in the right subtree return GetNearestGreaterOrEqual(root->right,pattern); } /* 2.1 GetNearestSmaller Returns a pointer to the biggest objectzs which is smaller than the argument. If no such object is stored in the current tree, NULL is returned. */ static contenttype const* GetNearestSmaller( Node const * const root, const contenttype& pattern) { __AVL_TRACE__ if(root==NULL) return NULL; contenttype value = root->content; if(Comparator::equal(value,pattern)){ return GetMax(root->left); } if(Comparator::smaller(value,pattern)){ // this is a candidate search for closer object in right subtree contenttype const* tmp = GetNearestSmaller(root->right,pattern); if(tmp){ return tmp; } else{ return &root->content; } } // search for smaller object return GetNearestSmaller(root->left,pattern); } /* 2.1 GetNearestGreater This function returns a pointer to the object stored in the tree which is the smallest one bigger than __pattern__. If pattern is bigger than all stored objects (or the tree is empty), NULL is returned. */ static contenttype const* GetNearestGreater( Node const * const root, const contenttype& pattern) { __AVL_TRACE__ if(root==NULL) return NULL; contenttype value = root->content; if(Comparator::equal(value,pattern)){ return GetMin(root->right); } if(Comparator::smaller(value,pattern)){ // search in the right tree for greater objects return GetNearestGreater(root->right,pattern); } contenttype const* tmp = GetNearestGreater(root->left,pattern); if(tmp){ return tmp; } else{ return &root->content; } } /* 2.1 GetMax Returns a pointer to the maximum entry or NULL if the tree is empty. */ static contenttype const* GetMax( Node const* const root) { __AVL_TRACE__ if(root==NULL) return NULL; Node const* tmp; // create tmp to keep root constant tmp = root; while(tmp->right){ tmp = tmp->right; } return &tmp->content; } /* 2.1 GetMin Returns a pointer to the minimum entry in the tree or NULL if the tree is empty. */ static contenttype const* GetMin( Node const* const root) { __AVL_TRACE__ if(root==NULL) return NULL; Node const* tmp; // create tmp to keep root constant tmp = root; while(tmp->left){ tmp = tmp->left; } return &tmp->content; } /* 2.1 Size Computes the number of nodes in the given subtree. */ static int Size(Node const * const root) { __AVL_TRACE__ if(root==NULL) return 0; return Size(root->left) + Size(root->right) + 1; } /** 3 Data Members 3.1 The root of this tree */ Node* root; } ; } // end of namespace avltree template std::ostream& operator<<(std::ostream& o,const avltree::AVLTree& tree){ tree.Print(o); return o; } #endif