AbstractSplayTree.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // AbstractSplayTree.h
00012 //
00028 #ifndef __AbstractSplayTree_h
00029 #define __AbstractSplayTree_h
00030 
00031 #ifdef __GNUC__
00032 #pragma interface
00033 #endif
00034  
00035 #ifdef NON_ANSI
00036 #include <iostream.h>
00037 #else
00038 #include <iostream>
00039 using namespace std;
00040 #endif
00041 #ifndef ANSI_HDRS
00042 #include <stdio.h>
00043 #else
00044 #include <cstdio>
00045 #endif
00046 #include "_generic.h"
00047 #include "AbstractSplayTree.h"
00048 #include "errmsg.h"
00049 #ifdef _MSC_VER
00050 #include "crtdbg.h"
00051 #endif
00052 #include "compare.h"
00053 
00054 #define node_size(x)   (((x)==NULL) ? 0 : ((x)->size))
00055 
00056 
00057 
00058 template <class T, class KEY>
00059 class AbstractSplayTree 
00060 {
00061 public:
00062 
00064   explicit AbstractSplayTree(const char* nameBuff = "Unnamed");
00066   virtual ~AbstractSplayTree() {}
00067   
00069   bool empty() const {return (tree == 0);}
00071   operator bool() const {return (tree != 0);}
00073   int size() const { return (tree ? tree->size : 0); }
00074 
00076   OrderSense sense() {return Sense;}
00078   void setSense(OrderSense sense_) {Sense=sense_;}
00079 
00081   void splay(const KEY& key)
00082                 {tree = exec_splay(&key,tree);}
00083 
00088   virtual T* find_rank(int r);
00094   virtual T* find(const KEY& key)
00095                 {
00096                 splay(key);
00097                 if (!tree) return tree;
00098                 if (tree->compare(key) == 0) return tree;
00099                 else                          return (T*)0;
00100                 }
00102   T* top()      {return tree;}
00103 
00105   virtual void add(KEY& key)
00106                 {insert(&key);}
00111   virtual void add(KEY& key, T*& item)
00112                 {item = insert(&key);}
00118   virtual void remove(KEY& key, bool& status)
00119                 {
00120                 T* tmp = find(key);
00121                 if (tmp) extract(tmp,status);
00122                 else     status = false;
00123                 }
00129   virtual void remove(T*& item, bool& status)
00130                 {
00131                 if (!item)
00132                    status = false;
00133                 else {
00134                    extract(item,status);
00135                    item = 0;
00136                    }
00137                 }
00143   virtual void remove(T*& item, KEY& key, bool& status)
00144                 {
00145                 if (!item)
00146                    status = false;
00147                 else {
00148                    key = item->key();
00149                    extract(item,status);
00150                    item = 0;
00151                    }
00152                 }
00153 
00155   int write(ostream& os);
00157   int read(istream& is);
00159   int rank(const KEY& key)
00160                 {
00161                 splay(key);
00162                 return (tree->left ? tree->left->size : 0);
00163                 }
00165   void clear();
00166 
00167 protected:
00168 
00169 //  void print_tree(ostream& os, int d, T* item);
00170 
00171 
00180   T* exec_splay(const KEY* key, T* item);
00182   virtual T* insert(KEY* key);
00188   virtual void extract(T* item, bool& status);
00189 
00191   T* tree;
00193   OrderSense Sense;
00195   const char* name;
00196 
00197 };
00198 
00199 
00200  
00201 template <class T, class KEY>
00202 inline UTILIB_API ostream& operator<<(ostream& output, 
00203                                                 AbstractSplayTree<T,KEY>& tree)
00204 { tree.write(output); return(output); }
00205  
00206 
00207 
00208 template <class T, class KEY>
00209 inline UTILIB_API istream& operator>>(istream& input,
00210                                                 AbstractSplayTree<T,KEY>& tree)
00211 { tree.read(input); return(input); }
00212  
00213 
00214 
00215 template <class T, class KEY>
00216 AbstractSplayTree<T,KEY>::AbstractSplayTree(const char* nameBuff)
00217         : tree(0),
00218           Sense(increasing),
00219           name(nameBuff)
00220 {
00221 if (!name)
00222    name = "";
00223 }
00224 
00225 
00226 
00227 template <class T, class KEY>
00228 T* AbstractSplayTree<T,KEY>::exec_splay(const KEY* key, T* t)
00229 {
00230     T N((KEY*)key), *l, *r, *y;
00231     int comp, l_size, r_size;
00232     
00233     if (t == 0) return t;
00234     comp = Sense*t->compare(*key);
00235     if (comp == 0) return t;
00236 
00237     N.left = N.right = NULL;
00238     l = r = &N;
00239     l_size = r_size = 0;
00240  
00241     while (1) {
00242         if (comp > 0) {
00243             if (t->left == NULL) break;
00244             if ((Sense*t->left->compare(*key)) > 0) {
00245                 y = t->left;                           /* rotate right */
00246                 t->left = y->right;
00247                 y->right = t;
00248                 t->size = node_size(t->left) + node_size(t->right) + 1;
00249                 t = y;
00250                 if (t->left == NULL) break;
00251             }
00252             r->left = t;                               /* link right */
00253             r = t;
00254             t = t->left;
00255             r_size += 1+ node_size(r->right);
00256         } else if (comp < 0) {
00257             if (t->right == NULL) break;
00258             if ((Sense*t->right->compare(*key)) < 0) {
00259                 y = t->right;                          /* rotate left */
00260                 t->right = y->left;
00261                 y->left = t;
00262                 t->size = node_size(t->left) + node_size(t->right) + 1;
00263                 t = y;
00264                 if (t->right == NULL) break;
00265             }
00266             l->right = t;                              /* link left */
00267             l = t;
00268             t = t->right;
00269             l_size += 1+ node_size(l->left);
00270         } else {
00271             break;
00272         }
00273         comp = Sense*t->compare(*key);
00274     }
00275     l_size += node_size(t->left);  /* Now l_size and r_size are the sizes of */
00276     r_size += node_size(t->right); /* the left and right trees we just built.*/
00277     t->size = l_size + r_size + 1;
00278 
00279     l->right = r->left = NULL;
00280 
00281     /* The following two loops correct the size fields of the right path  */
00282     /* from the left child of the root and the right path from the left   */
00283     /* child of the root.                                                 */
00284     for (y = N.right; y != NULL; y = y->right) {
00285         y->size = l_size;
00286         l_size -= 1+ node_size(y->left);
00287     }
00288     for (y = N.left; y != NULL; y = y->left) {
00289         y->size = r_size;
00290         r_size -= 1+ node_size(y->right);
00291     }
00292  
00293     l->right = t->left;                                /* assemble */
00294     r->left = t->right;
00295     t->left = N.right;
00296     t->right = N.left;
00297 
00298     return t;
00299 }
00300 
00301 
00302 
00303 template <class T, class KEY>
00304 T* AbstractSplayTree<T,KEY>::insert(KEY* newkey)
00305 {
00306     T* newroot = new T(newkey);
00307     if (tree == NULL) {
00308         newroot->left = newroot->right = NULL;
00309         }
00310     else {
00311         if ((Sense*newroot->compare(tree->key())) < 0) {
00312            newroot->left = tree->left;
00313            newroot->right = tree;
00314            tree->left = NULL;
00315            tree->size = 1+ node_size(tree->right);
00316         } else {
00317            newroot->right = tree->right;
00318            newroot->left = tree;
00319            tree->right = NULL;
00320            tree->size = 1+ node_size(tree->left);
00321         }
00322     }
00323     
00324     newroot->size = 1 + node_size(newroot->left) + node_size(newroot->right);
00325     tree = newroot;
00326     return tree;
00327 }
00328 
00329 
00330 
00331 template <class T, class KEY>
00332 void AbstractSplayTree<T,KEY>::extract(T* node, bool& status) {
00333     T* x;
00334     int tsize;
00335 
00336     if (tree==NULL) return;
00337     tsize = tree->size;
00338     tree = exec_splay(&(node->key()),tree);
00339     if ((Sense*node->compare(tree->key())) == 0) {               // found it
00340         status = true;
00341         if (tree->left == NULL) {
00342             x = tree->right;
00343         } else {
00344             x = exec_splay(&(node->key()), tree->left);
00345             x->right = tree->right;
00346         }
00347         delete tree;
00348         if (x != NULL) {
00349             x->size = tsize-1;
00350         }
00351         tree = x;
00352     }
00353     else {
00354         status = false;
00355         node = 0;
00356     }
00357 }
00358 
00359 
00360 
00361 template <class T, class KEY>
00362 T* AbstractSplayTree<T,KEY>::find_rank(int r)
00363 {
00364     T* tmp=tree;
00365     int lsize;
00366     if ((r < 0) || (r >= node_size(tmp))) return NULL;
00367     for (;;) {
00368         lsize = node_size(tmp->left);
00369         if (r < lsize) {
00370             tmp = tmp->left;
00371         } else if (r > lsize) {
00372             r = r - lsize - 1;
00373             tmp = tmp->right;
00374         } else {
00375             break;
00376         }
00377     }
00378     tree = exec_splay(&(tmp->key()),tree);
00379     return tmp;
00380 }
00381 
00382 /*
00383 void AbstractSplayTree<T,KEY>::print_tree(ostream& os, int d, 
00384                                         T* t) {
00385     int i;
00386     if (tree == NULL) return;
00387     print_tree(os,d+1,tree->right);
00388     for (i=0; i<d; i++) os << "  ";
00389     dowrite(tree,os);
00390     //os << "(" << node_size(tree) << "," << tree->ctr << ")" << endl;
00391     print_tree(os,d+1,tree->left);
00392 }
00393 */
00394 
00395 
00396 
00397 template <class T, class KEY>
00398 int AbstractSplayTree<T,KEY>::write(ostream& os)
00399 {
00400 os << size() << endl;
00401 
00402 T* node;
00403 node = find_rank(0);
00404 int i=1;
00405 while (node) {
00406   //os << node->ctr << " ";
00407   node->write(os);
00408   os << endl;
00409   node = find_rank(i++);
00410   }
00411 
00412 return 0;
00413 }
00414 
00415 
00416 
00417 template <class T, class KEY>
00418 int AbstractSplayTree<T,KEY>::read(istream& is)
00419 {
00420 int Size;
00421 is >> Size;
00422 for (int i=0; i<Size; i++) {
00423   T* item;
00424   item->read(is);
00425   add(item);
00426   }
00427 
00428 return OK;
00429 }
00430 
00431 
00432 
00433 template <class T, class KEY>
00434 void AbstractSplayTree<T,KEY>::clear()
00435 {
00436 bool status;
00437 while (tree) {
00438   remove(tree,status);
00439   if (!status)
00440      ErrAbort("AbstractSplayTree<T,KEY>::clear - problem removing the root of the splay tree.");
00441   }
00442 }
00443 
00444 #undef node_size
00445 #endif