LTP GCOV extension - code coverage report
Current view: directory - include/utilib - AbstractSplayTree.h
Test: Acro
Date: 2008-10-21 Instrumented lines: 168
Code covered: 87.5 % Executed lines: 147

       1                 : /*  _________________________________________________________________________
       2                 :  *
       3                 :  *  UTILIB: A utility library for developing portable C++ codes.
       4                 :  *  Copyright (c) 2001, Sandia National Laboratories.
       5                 :  *  This software is distributed under the GNU Lesser General Public License.
       6                 :  *  For more information, see the README file in the top UTILIB directory.
       7                 :  *  _________________________________________________________________________
       8                 :  */
       9                 : 
      10                 : /**
      11                 :  * \file AbstractSplayTree.h
      12                 :  *
      13                 :  * Defines the utilib::AbstractSplayTree class
      14                 :  */
      15                 : 
      16                 : #ifndef utilib_AbstractSplayTree_h
      17                 : #define utilib_AbstractSplayTree_h
      18                 : 
      19                 : #include <utilib/utilib_config.h>
      20                 : #include <utilib/std_headers.h>
      21                 : 
      22                 : #ifdef _MSC_VER
      23                 : /* TODO - Try compiling with msvc and find out if this is needed.*/
      24                 : #include "crtdbg.h"
      25                 : #endif
      26                 : 
      27                 : #include <utilib/_generic.h>
      28                 : #include <utilib/AbstractSplayTree.h>
      29                 : #include <utilib/exception_mngr.h>
      30                 : #include <utilib/compare.h>
      31                 : #include <utilib/PackBuf.h>
      32                 : 
      33                 : namespace utilib {
      34                 : 
      35                 : /// A simple macro used internally for the splay tree code.
      36                 : #define node_size(x)   (((x)==NULL) ? 0 : ((x)->size))
      37                 : 
      38                 : 
      39                 : /**
      40                 :  * Implements an abstract class for defining the core operations of a
      41                 :  * top-down splay tree.
      42                 :  *
      43                 :  * This is adapted from code developed by D. Sleator, which itself is 
      44                 :  * adapted from simple top-down splay, at the bottom of 669 of 
      45                 :  * \if GeneratingLaTeX Sleator and Tarjan~\cite{SleTar85}. \endif
      46                 :  * \if GeneratingHTML SleTar85. \endif
      47                 :  * Sleator's code can be aquired from
      48                 :  *
      49                 :  *   http://www-cgi.cs.cmu.edu/afs/cs/user/sleator/www/home.html
      50                 :  */
      51                 : template <class T, class KEY>
      52                 : class AbstractSplayTree
      53                 : {
      54                 : public:
      55                 : 
      56                 :   /// Constructor, which specifies a name for the tree.
      57                 :   explicit AbstractSplayTree(const char* nameBuff = "Unnamed");
      58                 : 
      59                 :   /// Destructor.
      60             262 :   virtual ~AbstractSplayTree() {clear();}
      61                 :   
      62                 :   /// Copy operator
      63                 :   AbstractSplayTree<T,KEY>& operator=(const AbstractSplayTree<T,KEY>& tree);
      64                 : 
      65                 :   /// Returns \c true if the tree is empty and \c false otherwise.
      66                 :   bool empty() const {return (tree == 0);}
      67                 : 
      68                 :   /// Returns \c true if the tree is not empty and \c false otherwise.
      69                 :   operator bool() const {return (tree != 0);}
      70                 : 
      71                 :   /// Returns the size of the splay tree.
      72          400659 :   int size() const { return (tree ? tree->size : 0); }
      73                 : 
      74                 :   /// Return the value of \c Sense.
      75                 :   OrderSense sense() {return Sense;}
      76                 : 
      77                 :   /// Set the value of \c Sense.
      78                 :   void setSense(OrderSense sense_) {Sense=sense_;}
      79                 : 
      80                 :   /// Perform a splay operation starting from the root of the tree.
      81          117558 :   void splay(const KEY& key)
      82          117558 :                 {tree = exec_splay(&key,tree);}
      83                 : 
      84                 :   /**
      85                 :    * Return the item in the splay tree with rank \a r.
      86                 :    * Returns a null item if a bad rank value is passed in.
      87                 :    */
      88                 :   virtual T* find_rank(int r);
      89                 : 
      90                 :   /**
      91                 :    * Return the item in the splay tree with rank \a r.
      92                 :    * Returns a null item if a bad rank value is passed in.
      93                 :    */
      94           10701 :   virtual const T* find_rank(int r) const
      95                 :         {
      96           10701 :         AbstractSplayTree<T,KEY>* Tthis = const_cast< AbstractSplayTree<T,KEY>* >(this);
      97           10701 :         T* tmp = Tthis->find_rank(r);
      98           10701 :         return tmp;
      99                 :         }
     100                 : 
     101                 :   /**
     102                 :    * Return the item in the splay tree with the given key.
     103                 :    * Returns null if the tree is empty or if the item is not
     104                 :    * in the tree.
     105                 :    */
     106               0 :   virtual T* find(const KEY& key)
     107                 :                 {
     108               0 :                 splay(key);
     109               0 :                 if (!tree) return tree;
     110               0 :                 if (tree->compare(key) == 0) return tree;
     111               0 :                 else                          return (T*)0;
     112                 :                 }
     113                 : 
     114                 :   /// Return the top of the splay tree.
     115          270584 :   T* top()      {return tree;}
     116                 : 
     117                 :   /// Return the top of the splay tree.
     118                 :   const T* top() const  {return tree;}
     119                 : 
     120                 :   /**
     121                 :    * Add a key to the splay tree and return the splay tree item
     122                 :    * that contains it.
     123                 :    */
     124          170701 :   virtual T* add(KEY& key)
     125          170701 :                 {return insert(&key);}
     126                 : 
     127                 :   /**
     128                 :    * Remove a splay tree item with the given key.
     129                 :    * The status flag is \c true if the key was found and \c false
     130                 :    * otherwise.
     131                 :    */
     132               0 :   virtual void remove(KEY& key, bool& status)
     133                 :                 {
     134               0 :                 T* tmp = find(key);
     135               0 :                 if (tmp) extract(tmp,status);
     136               0 :                 else     status = false;
     137                 :                 }
     138                 : 
     139                 :   /**
     140                 :    * Remove a splay tree item.
     141                 :    * The status flag is \c true if the item was found and \c false
     142                 :    * otherwise.
     143                 :    */
     144           99883 :   virtual void remove(T*& item, bool& status)
     145                 :                 {
     146           99883 :                 if (!item)
     147               0 :                    status = false;
     148                 :                 else {
     149           99883 :                    extract(item,status);
     150           99883 :                    item = 0;
     151                 :                    }
     152                 :                 }
     153                 : 
     154                 :   /**
     155                 :    * Remove a splay tree item and return the item's key.
     156                 :    * The status flag is \c true if the item was found and \c false
     157                 :    * otherwise.
     158                 :    */
     159               0 :   virtual void remove(T*& item, KEY& key, bool& status)
     160                 :                 {
     161               0 :                 if (!item)
     162               0 :                    status = false;
     163                 :                 else {
     164               0 :                    key = item->key();
     165               0 :                    extract(item,status);
     166               0 :                    item = 0;
     167                 :                    }
     168                 :                 }
     169                 : 
     170                 :   /// Returns the rank of the top (0...size-1)
     171          117558 :   int rank(const KEY& key)
     172                 :                 {
     173          117558 :                 splay(key);
     174          117558 :                 if (!tree) return 0;
     175          117558 :                 return (tree->left ? tree->left->size : 0);
     176                 :                 }
     177                 : 
     178                 :   ///
     179             626 :   void balance() const
     180                 :                 {
     181             626 :                 int n = size()/2;
     182             626 :                 find_rank(n);
     183                 :                 }
     184                 : 
     185                 :   /// Empty out a splay tree.
     186                 :   void clear(T* ptr=0);
     187                 : 
     188                 : protected:
     189                 : 
     190                 : //  void print_tree(ostream& os, int d, T* item);
     191                 : 
     192                 : 
     193                 :   /**
     194                 :    * Search for an item with a given key on a tree rooted at \a item.  
     195                 :    * If an item is found in the tree, it is splayed to the root.
     196                 :    * Otherwise, the item put at the root is the last one before \c NULL 
     197                 :    * that would have been reached in a normal binary search.  
     198                 :    * (It is a neighbor of i in the tree.)  This method of splaying 
     199                 :    * is very convenient for facilitating a variety of other operations.
     200                 :    */
     201                 :   T* exec_splay(const KEY* key, T* item);
     202                 : 
     203                 :   /// Add a key to the tree.
     204                 :   virtual T* insert(KEY* key);
     205                 : 
     206                 :   /**
     207                 :    * Remove a splay tree item.
     208                 :    * The status flag is \c true if the item was found and \c false
     209                 :    * otherwise.
     210                 :    */
     211                 :   virtual void extract(T* item, bool& status);
     212                 : 
     213                 :   /// The current root of the splay tree.
     214                 :   T* tree;
     215                 : 
     216                 :   /// Specifies the ordering within the tree: increasing or decreasing.
     217                 :   OrderSense Sense;
     218                 : 
     219                 :   /// The name of the class instance.
     220                 :   const char* name;
     221                 : 
     222                 : };
     223                 : 
     224                 : 
     225                 :  
     226                 : 
     227                 : 
     228                 : template <class T, class KEY>
     229             262 : AbstractSplayTree<T,KEY>::AbstractSplayTree(const char* nameBuff)
     230                 :         : tree(0),
     231                 :           Sense(increasing),
     232             262 :           name(nameBuff)
     233                 : {
     234             262 : if (!name)
     235               0 :    name = "";
     236                 : }
     237                 : 
     238                 : 
     239                 : 
     240                 : template <class T, class KEY>
     241                 : AbstractSplayTree<T,KEY>& 
     242                 :         AbstractSplayTree<T,KEY>::operator=(
     243             381 :                                         const AbstractSplayTree<T,KEY>& t)
     244                 : {
     245             381 : if (t.tree) {
     246                 :    // Balance the tree first to avoid pathological behavior
     247             381 :    t.balance();
     248             381 :    tree = t.tree->clone();
     249                 :    }
     250                 : else
     251               0 :    tree = 0;
     252             381 : Sense = t.Sense;
     253             381 : name = "";
     254             381 : return *this;
     255                 : }
     256                 : 
     257                 : 
     258                 : template <class T, class KEY>
     259          699794 : T* AbstractSplayTree<T,KEY>::exec_splay(const KEY* key, T* t)
     260                 : {
     261          699794 :     T N((KEY*)key), *l, *r, *y;
     262                 :     int comp, l_size, r_size;
     263                 :     
     264          699794 :     if (t == 0) return t;
     265          699682 :     comp = Sense*t->compare(*key);
     266          699682 :     if (comp == 0) return t;
     267                 : 
     268          350596 :     N.left = N.right = NULL;
     269          350596 :     l = r = &N;
     270          350596 :     l_size = r_size = 0;
     271                 :  
     272          506975 :     while (1) {
     273          857571 :         if (comp > 0) {
     274          262551 :             if (t->left == NULL) break;
     275          258932 :             if ((Sense*t->left->compare(*key)) > 0) {
     276          140427 :                 y = t->left;                           /* rotate right */
     277          140427 :                 t->left = y->right;
     278          140427 :                 y->right = t;
     279          140427 :                 t->size = node_size(t->left) + node_size(t->right) + 1;
     280          140427 :                 t = y;
     281          140427 :                 if (t->left == NULL) break;
     282                 :             }
     283          257311 :             r->left = t;                               /* link right */
     284          257311 :             r = t;
     285          257311 :             t = t->left;
     286          257311 :             r_size += 1+ node_size(r->right);
     287          595020 :         } else if (comp < 0) {
     288          457446 :             if (t->right == NULL) break;
     289          252825 :             if ((Sense*t->right->compare(*key)) < 0) {
     290          106018 :                 y = t->right;                          /* rotate left */
     291          106018 :                 t->right = y->left;
     292          106018 :                 y->left = t;
     293          106018 :                 t->size = node_size(t->left) + node_size(t->right) + 1;
     294          106018 :                 t = y;
     295          106018 :                 if (t->right == NULL) break;
     296                 :             }
     297          249664 :             l->right = t;                              /* link left */
     298          249664 :             l = t;
     299          249664 :             t = t->right;
     300          249664 :             l_size += 1+ node_size(l->left);
     301                 :         } else {
     302          137574 :             break;
     303                 :         }
     304          506975 :         comp = Sense*t->compare(*key);
     305                 :     }
     306          350596 :     l_size += node_size(t->left);  /* Now l_size and r_size are the sizes of */
     307          350596 :     r_size += node_size(t->right); /* the left and right trees we just built.*/
     308          350596 :     t->size = l_size + r_size + 1;
     309                 : 
     310          350596 :     l->right = r->left = NULL;
     311                 : 
     312                 :     /* The following two loops correct the size fields of the right path  */
     313                 :     /* from the left child of the root and the right path from the left   */
     314                 :     /* child of the root.                                                 */
     315          600260 :     for (y = N.right; y != NULL; y = y->right) {
     316          249664 :         y->size = l_size;
     317          249664 :         l_size -= 1+ node_size(y->left);
     318                 :     }
     319          607907 :     for (y = N.left; y != NULL; y = y->left) {
     320          257311 :         y->size = r_size;
     321          257311 :         r_size -= 1+ node_size(y->right);
     322                 :     }
     323                 :  
     324          350596 :     l->right = t->left;                                /* assemble */
     325          350596 :     r->left = t->right;
     326          350596 :     t->left = N.right;
     327          350596 :     t->right = N.left;
     328                 : 
     329          350596 :     return t;
     330                 : }
     331                 : 
     332                 : 
     333                 : 
     334                 : template <class T, class KEY>
     335          113087 : T* AbstractSplayTree<T,KEY>::insert(KEY* newkey)
     336                 : {
     337          113087 :     T* newroot = new T(newkey);
     338          113087 :     if (tree == NULL) {
     339             112 :         newroot->left = newroot->right = NULL;
     340                 :         }
     341                 :     else {
     342          112975 :         if ((Sense*newroot->compare(tree->key())) < 0) {
     343            5197 :            newroot->left = tree->left;
     344            5197 :            newroot->right = tree;
     345            5197 :            tree->left = NULL;
     346            5197 :            tree->size = 1+ node_size(tree->right);
     347                 :         } else {
     348          107778 :            newroot->right = tree->right;
     349          107778 :            newroot->left = tree;
     350          107778 :            tree->right = NULL;
     351          107778 :            tree->size = 1+ node_size(tree->left);
     352                 :         }
     353                 :     }
     354                 :     
     355          113087 :     newroot->size = 1 + node_size(newroot->left) + node_size(newroot->right);
     356          113087 :     tree = newroot;
     357          113087 :     return tree;
     358                 : }
     359                 : 
     360                 : 
     361                 : 
     362                 : template <class T, class KEY>
     363           99883 : void AbstractSplayTree<T,KEY>::extract(T* node, bool& status) {
     364                 :     T* x;
     365                 :     int tsize;
     366                 : 
     367           99883 :     if (tree==NULL) return;
     368           99883 :     tsize = tree->size;
     369           99883 :     tree = exec_splay(&(node->key()),tree);
     370           99883 :     if ((Sense*node->compare(tree->key())) == 0) {               // found it
     371           99883 :         status = true;
     372           99883 :         if (tree->left == NULL) {
     373               0 :             x = tree->right;
     374                 :         } else {
     375           99883 :             x = exec_splay(&(node->key()), tree->left);
     376           99883 :             x->right = tree->right;
     377                 :         }
     378           99883 :         delete tree;
     379           99883 :         if (x != NULL) {
     380           99883 :             x->size = tsize-1;
     381                 :         }
     382           99883 :         tree = x;
     383                 :     }
     384                 :     else {
     385               0 :         status = false;
     386               0 :         node = 0;
     387                 :     }
     388                 : }
     389                 : 
     390                 : 
     391                 : 
     392                 : template <class T, class KEY>
     393          111891 : T* AbstractSplayTree<T,KEY>::find_rank(int r)
     394                 : {
     395          111891 :     T* tmp=tree;
     396                 :     int lsize;
     397          111891 :     if ((r < 0) || (r >= node_size(tmp))) return NULL;
     398           39066 :     for (;;) {
     399          150952 :         lsize = node_size(tmp->left);
     400          150952 :         if (r < lsize) {
     401           25267 :             tmp = tmp->left;
     402          125685 :         } else if (r > lsize) {
     403           13799 :             r = r - lsize - 1;
     404           13799 :             tmp = tmp->right;
     405                 :         } else {
     406          111886 :             break;
     407                 :         }
     408                 :     }
     409          111886 :     tree = exec_splay(&(tmp->key()),tree);
     410          111886 :     return tmp;
     411                 : }
     412                 : 
     413                 : #if 0
     414                 : void AbstractSplayTree<T,KEY>::print_tree(ostream& os, int d, 
     415                 :                                         T* t) {
     416                 :     int i;
     417                 :     if (tree == NULL) return;
     418                 :     print_tree(os,d+1,tree->right);
     419                 :     for (i=0; i<d; i++) os << "  ";
     420                 :     dowrite(tree,os);
     421                 :     //os << "(" << node_size(tree) << "," << tree->ctr << ")" << endl;
     422                 :     print_tree(os,d+1,tree->left);
     423                 : }
     424                 : #endif
     425                 : 
     426                 : 
     427                 : template <class T, class KEY>
     428           27348 : void AbstractSplayTree<T,KEY>::clear(T* ptr)
     429                 : {
     430           27348 : if (!ptr) {
     431             514 :    if (tree) {
     432                 :       // Before we clear the tree, we rebalance it
     433                 :       // This prevents pathological cases where clear recurses so 
     434                 :       // long that it eats up the stack!
     435             245 :       balance();
     436                 :       // Clear the tree
     437             245 :       clear(tree);
     438             245 :       tree=0;
     439                 :       }
     440             514 :    return;
     441                 :    }
     442           26834 : if (ptr->left)
     443           19703 :    clear(ptr->left);
     444           26834 : if (ptr->right)
     445            6886 :    clear(ptr->right);
     446           26834 : delete ptr;
     447                 : }
     448                 : 
     449                 : #undef node_size
     450                 : 
     451                 : } // namespace utilib
     452                 : 
     453                 : /// Out-stream operator for writing the contents of a AbstractSplayTree
     454                 : template <class T, class KEY>
     455               5 : inline std::ostream& operator<<(std::ostream& os, const utilib::AbstractSplayTree<T,KEY>& obj)
     456                 : {
     457               5 : os << obj.size() << std::endl;
     458                 : 
     459               5 : const T* node = obj.find_rank(0);
     460               5 : int i=1;
     461           10080 : while (node) {
     462                 :   //os << node->ctr << " ";
     463           10070 :   node->write(os);
     464           10070 :   os << std::endl;
     465           10070 :   node = obj.find_rank(i++);
     466                 :   }
     467               5 : return os;
     468                 : }
     469                 : 
     470                 : /// Out-stream operator for writing the contents of a AbstractSplayTree
     471                 : template <class T, class KEY>
     472                 : inline utilib::PackBuffer& operator<<(utilib::PackBuffer& os,
     473                 :                                         const utilib::AbstractSplayTree<T,KEY>& obj)
     474                 : {
     475                 : os << obj.size();
     476                 : 
     477                 : const T* node = obj.find_rank(0);
     478                 : int i=1;
     479                 : while (node) {
     480                 :   node->write(os);
     481                 :   node = obj.find_rank(i++);
     482                 :   }
     483                 : return os;
     484                 : }
     485                 : 
     486                 : 
     487                 : /// In-stream operator for reading the contents of a AbstractSplayTree
     488                 : template <class T, class KEY>
     489                 : inline std::istream& operator>>(std::istream& is, utilib::AbstractSplayTree<T,KEY>& obj)
     490                 : {
     491                 : int Size;
     492                 : is >> Size;
     493                 : for (int i=0; i<Size; i++) {
     494                 :   T* item = 0;
     495                 :   item->read(is);
     496                 :   obj.add(item);
     497                 :   }
     498                 : return is;
     499                 : }
     500                 : 
     501                 : /// In-stream operator for reading the contents of a AbstractSplayTree
     502                 : template <class T, class KEY>
     503                 : inline utilib::UnPackBuffer& operator>>(utilib::UnPackBuffer& is,
     504                 :                                         utilib::AbstractSplayTree<T,KEY>& obj)
     505                 : {
     506                 : int Size;
     507                 : is >> Size;
     508                 : for (int i=0; i<Size; i++) {
     509                 :   T* item = 0;
     510                 :   item->read(is);
     511                 :   obj.add(item);
     512                 :   }
     513                 : return is;
     514                 : }
     515                 : 
     516                 : 
     517                 : 
     518                 : #endif

Generated by: LTP GCOV extension version 1.4