IBSTree.h

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 // $Id$
00032 
00033 #ifndef _IBSTree_h_
00034 #define _IBSTree_h_
00035 
00036 /*******************************************************/
00037 /*      header files                   */
00038 /*******************************************************/
00039 
00040 #include <assert.h>
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include "dyntypes.h"
00044 
00045 #include <set>
00046 #include <limits>
00047 
00048 using namespace std;
00049 
00050 /** Templape class for Interval Binary Search Tree. The implementation is
00051   * based on a red-black tree (derived from our codeRange implementation)
00052   * to control the tree height and thus insertion and search cost.
00053   *
00054   * Unlike our codeRangeTree, this data structure can represent overlapping
00055   * intervals. It is useful for executing stabbing queries and more
00056   * generally for finding invervals that overlap a particular interval.
00057   * A stabbing query requires O(log(N) + L) time in the worst case, where
00058   * L is the number of overlapping intervals, and insertion requires
00059   * O(log^2(N)) time (compare to O(log(N)) for a standard RB-tree).
00060   *
00061   * This class requires a worst case storage O(N log(N))
00062   *
00063   * For more information:
00064   *
00065   * @TECHREPORT{Hanson90theibs-tree:,
00066   *     author = {Eric N. Hanson and Moez Chaabouni},
00067   *     title = {The IBS-tree: A data structure for finding all intervals that overlap a point},
00068   *     institution = {},
00069   *     year = {1990}
00070   * }
00071   **/
00072 
00073 /** EXTREMELY IMPORTANT XXX: Assuming that all intervals have lower bound
00074     predicate <= and upper bound predicate > ; that is, intervals are 
00075     [a,b) **/
00076 
00077 // windows.h defines min(), max() macros that interfere with numeric_limits
00078 #undef min
00079 #undef max
00080 
00081 namespace Dyninst {
00082 
00083 namespace IBS {
00084 typedef enum { TREE_RED, TREE_BLACK } color_t;
00085 };
00086 
00087 template<class T = unsigned long>
00088 class interval {
00089   public:
00090     interval() { }
00091     virtual ~interval() { }
00092 
00093     virtual T low() const = 0;
00094     virtual T high() const = 0;
00095 
00096     typedef T type;
00097 };
00098 
00099 class SimpleInterval : public interval<int> {
00100   public:
00101     SimpleInterval( interval<int> & i, void * id ) {
00102         low_ = i.low();
00103         high_ = i.high();
00104         id_ = id;
00105     }
00106     SimpleInterval(int low, int high, void * id) {
00107         low_ = low;
00108         high_ = high;
00109         id_ = id;
00110     }
00111 
00112     virtual int low() const { return low_; }
00113     virtual int high() const { return high_; }
00114 
00115   private:
00116     int low_;
00117     int high_;
00118     void * id_; // some arbitrary unique identifier
00119 };
00120 
00121 template<class ITYPE>
00122 class IBSTree;
00123 
00124 template<class ITYPE = interval<> >
00125 class IBSNode {
00126     friend class IBSTree<ITYPE>;
00127     typedef typename ITYPE::type interval_type;
00128   public:
00129     IBSNode() : 
00130         color(IBS::TREE_BLACK),
00131         left(NULL),
00132         right(NULL),
00133         parent(NULL) { }
00134 
00135     /** constructor for non-nil elements **/
00136     IBSNode(interval_type value, IBSNode *n) :
00137         val_(value),
00138         left(n),
00139         right(n),
00140         parent(NULL) { }
00141 
00142     ~IBSNode() { }
00143 
00144     interval_type value() const { return val_; };
00145 
00146   private: 
00147     /* The endpoint of an interval range */
00148     interval_type val_;
00149 
00150     /* Intervals indexed by this node */
00151     set<ITYPE *> less;
00152     set<ITYPE *> greater;
00153     set<ITYPE *> equal;
00154 
00155     IBS::color_t color;
00156 
00157     IBSNode<ITYPE> *left;
00158     IBSNode<ITYPE> *right;
00159     IBSNode<ITYPE> *parent;
00160 };
00161 
00162 template<class ITYPE = interval<> >
00163 class IBSTree {
00164     typedef typename ITYPE::type interval_type;
00165 
00166     IBSNode<ITYPE> *nil;
00167 
00168     /** size of tree **/
00169     int treeSize;
00170 
00171     /** pointer to the tree root **/
00172     IBSNode<ITYPE> *root;
00173 
00174     /** RB-tree left rotation with modification to enforce IBS invariants **/
00175     void leftRotate(IBSNode<ITYPE> *);
00176 
00177     /** RB-tree right rotation with modification to enforce IBS invariants **/
00178     void rightRotate(IBSNode<ITYPE> *);
00179 
00180     /** Node deletion **/
00181     void deleteFixup(IBSNode<ITYPE> *);
00182 
00183     void removeInterval(IBSNode<ITYPE> *R, ITYPE *range);
00184 
00185     /** Insertion operations: insert the left or right endpoint of
00186         an interval into the tree (may or may not add a node **/
00187     IBSNode<ITYPE>* addLeft(ITYPE *I, IBSNode<ITYPE> *R);
00188     IBSNode<ITYPE>* addRight(ITYPE *I, IBSNode<ITYPE> *R);
00189 
00190     /** Find the lowest valued ancestor of node R that has R in its
00191         left subtree -- used in addLeft to determine whether all of
00192         the values in R's right subtree are covered by an interval **/
00193     interval_type rightUp(IBSNode<ITYPE> *R);
00194 
00195     /** Symmetric to rightUp **/
00196     interval_type leftUp(IBSNode<ITYPE> *R);
00197 
00198     /** Tree-balancing algorithm on insertion **/
00199     void insertFixup(IBSNode<ITYPE> *x);
00200 
00201     /** Finds the precessor of the node; this node will have its value
00202         copied to the target node of a deletion and will itself be deleted **/
00203     //IBSNode* treePredecessor(IBSNode *);
00204 
00205     /** Find a node with the provided value (interval endpoint) **/
00206     //IBSNode* findNode(int) const;
00207 
00208     /** Delete all nodes in the subtree rooted at the parameter **/
00209     void destroy(IBSNode<ITYPE> *);
00210 
00211     void findIntervals(interval_type X, IBSNode<ITYPE> *R, set<ITYPE *> &S) const;
00212     void findIntervals(ITYPE *I, IBSNode<ITYPE> *R, set<ITYPE *> &S) const;
00213 
00214     void PrintPreorder(IBSNode<ITYPE> *n);
00215 
00216     int height(IBSNode<ITYPE> *n);
00217     int CountMarks(IBSNode<ITYPE> *R) const;
00218 
00219     unsigned MemUse() const;
00220 
00221   public:
00222 
00223     /** public for debugging purposes **/
00224     //StatContainer stats_;
00225 
00226     IBSTree() : treeSize(0) {
00227         nil = new IBSNode<ITYPE>;
00228         root = nil;
00229         //stats_.add("insert",TimerStat);
00230         //stats_.add("remove",TimerStat);
00231     }     
00232 
00233     ~IBSTree() {
00234         destroy(root);
00235         delete nil;
00236     }
00237 
00238     int size() const { return treeSize; }
00239     int CountMarks() const;
00240     
00241     bool empty() const { return (root == nil); }
00242 
00243     void insert(ITYPE *);
00244 
00245     void remove(ITYPE *);
00246 
00247     /** Find all intervals that overlap the provided point. Returns
00248         the number of intervals found **/  
00249     int find(interval_type, set<ITYPE *> &) const;
00250     int find(ITYPE *I, set<ITYPE *> &) const;
00251 
00252     /** Finds the very next interval(s) with left endpoint
00253         = supremum(X) **/
00254     void successor(interval_type X, set<ITYPE *> &) const; 
00255     /** Use only when no two intervals share the same lower bound **/
00256     ITYPE * successor(interval_type X) const;
00257 
00258     /** Delete all entries in the tree **/
00259     void clear();
00260 
00261     void PrintPreorder() { PrintPreorder(root); }
00262 };
00263 
00264 template<class ITYPE>
00265 void IBSTree<ITYPE>::rightRotate(IBSNode<ITYPE> *pivot)
00266 {
00267     if(!pivot || (pivot == nil))
00268         return;
00269 
00270     IBSNode<ITYPE> *y = pivot->left;
00271     if(y == nil)
00272         return;
00273     pivot->left = y->right;
00274     if(y->right != nil)
00275         y->right->parent = pivot;
00276     y->parent = pivot->parent;
00277     if(!pivot->parent) {
00278         root = y;
00279     }
00280     else if(pivot == pivot->parent->left)
00281         pivot->parent->left = y;
00282     else
00283         pivot->parent->right = y;
00284     y->right = pivot;
00285     pivot->parent = y;
00286 
00287     /* Maintain the IBS annotation invariants */
00288     
00289     // 1. Copy all marks from the < slot of the pivot (old subtree root)
00290     //    to the < and = slots of y (new subtree root). Maintains containment.
00291     y->less.insert(pivot->less.begin(), pivot->less.end());
00292     y->equal.insert(pivot->less.begin(), pivot->less.end());
00293 
00294     // 2. For each mark in y's > slot, if it was not in pivot's >,
00295     //    *move* it to pivot's <. Maintains containment and maximality,
00296     //    because it ensures that nodes under y->right covered by
00297     //    the mark before rotation are now (which are now under pivot->left)
00298     //    are still covered by the mark (if y > can't cover them still)
00299     
00300     // 3. Simultaneously, if the mark in in y's > slot AND pivot's > slot 
00301     //    (before rotation), remove the mark from pivot's > and = slots
00302     //    (preserving maximality).
00303 
00304     typename set< ITYPE * >::iterator it = y->greater.begin();
00305     while( it != y->greater.end() )
00306     {
00307         ITYPE *tmp = *it;
00308     
00309         typename set< ITYPE *>::iterator pit = pivot->greater.find( tmp );
00310         if(pit == pivot->greater.end()) {
00311             // Case 2
00312             pivot->less.insert( tmp );
00313             // remove from y's >. This invalidates the iterator, so
00314             // update first
00315             typename set< ITYPE * >::iterator del = it;
00316             ++it;
00317             y->greater.erase( del );
00318         } else {
00319             // Case 3
00320             // remove from pivot's >
00321             pivot->greater.erase( pit );
00322             pit = pivot->equal.find( tmp );
00323             if(pit != pivot->equal.end())
00324                 pivot->equal.erase( pit );
00325     
00326             ++it;
00327         }
00328     }
00329 }
00330 
00331 template<class ITYPE>
00332 void IBSTree<ITYPE>::leftRotate(IBSNode<ITYPE> *pivot)
00333 {
00334     if(!pivot || (pivot == nil))
00335         return;
00336 
00337     IBSNode<ITYPE> *y = pivot->right;
00338 
00339     if(y == nil)
00340         return;
00341 
00342     pivot->right = y->left;
00343     if(y->left != nil)
00344         y->left->parent = pivot;
00345     y->parent = pivot->parent;
00346     if(!pivot->parent) {
00347         root = y;
00348     }
00349     else if(pivot == pivot->parent->left)
00350         pivot->parent->left = y;
00351     else
00352         pivot->parent->right = y;
00353     y->left = pivot;
00354     pivot->parent = y;
00355 
00356     /* Fix up the IBS annotations. These are exactly opposeite of the
00357        rules for right rotation */
00358     
00359     y->greater.insert(pivot->greater.begin(),pivot->greater.end());
00360     y->equal.insert(pivot->greater.begin(),pivot->greater.end());
00361 
00362     typename set< ITYPE * >::iterator it = y->less.begin();
00363     while( it != y->less.end() )
00364     {
00365         ITYPE *tmp = *it;
00366     
00367         typename set< ITYPE *>::iterator pit = pivot->less.find( tmp );
00368         if(pit == pivot->less.end()) {
00369             // Case 2
00370             pivot->greater.insert( tmp );
00371             // remove from y's <. This invalidates the iterator, so
00372             // update first
00373             typename set< ITYPE * >::iterator del = it;
00374             ++it;
00375             y->less.erase( del );
00376         } else {
00377             // Case 3
00378             // remove from pivot's < and =
00379             pivot->less.erase( pit );
00380             pit = pivot->equal.find( tmp );
00381             if(pit != pivot->equal.end())
00382                 pivot->equal.erase( pit );
00383     
00384             ++it;
00385         }
00386     }
00387 }
00388 
00389 template<class ITYPE>
00390 IBSNode<ITYPE>* 
00391 IBSTree<ITYPE>::addLeft(ITYPE *I, IBSNode<ITYPE> *R)
00392 {
00393     IBSNode<ITYPE> *parent = NULL;
00394 
00395     // these calls can't be inlined as they're to virtuals
00396     interval_type ilow = I->low();
00397     interval_type ihigh = I->high();
00398 
00399     while(1) {
00400         bool created = false;
00401         if(R == nil) {
00402             // create a new node
00403             IBSNode<ITYPE> *tmp = new IBSNode<ITYPE>( ilow, nil );
00404             treeSize++;
00405             created = true;
00406            
00407             if(parent == NULL)  // must be the root
00408                 root = tmp;
00409             else {
00410                 tmp->parent = parent;
00411                 if(tmp->value() < parent->value()) {
00412                     parent->left = tmp;
00413                 } else if(tmp->value() > parent->value()) {
00414                     parent->right = tmp;
00415                 } else {
00416                     assert(0); // can't get here
00417                 }
00418             }
00419             R = tmp;
00420         }
00421 
00422         interval_type rval = R->value();
00423     
00424         if(rval == ilow) {
00425             if( rightUp(R) <= ihigh ) {
00426                 R->greater.insert( I );
00427             }
00428             R->equal.insert( I );   // assumes closed lower bound
00429     
00430             if(created)
00431                 return R;
00432             else
00433                 return NULL;
00434         }
00435         else if(rval < ilow) {
00436             parent = R;
00437             R = R->right;
00438             continue;
00439         }
00440         else if(rval > ilow) {
00441             if(rval < ihigh) {
00442                 R->equal.insert( I );
00443             }
00444             if( rightUp(R) <= ihigh ) {
00445                 R->greater.insert( I );
00446             }
00447             parent = R;
00448             R = R->left;
00449             continue;
00450         } else {
00451             assert(0);  // can't get here, but gcc whines
00452             return NULL;
00453         }
00454     }
00455 
00456     assert(0);
00457     return NULL;    // make GCC happy
00458 }
00459 
00460 template<class ITYPE>
00461 IBSNode<ITYPE> *
00462 IBSTree<ITYPE>::addRight(ITYPE *I, IBSNode<ITYPE> *R)
00463 {
00464     IBSNode<ITYPE> *parent = NULL;
00465 
00466     // these calls can't be inlined as they're to virtuals
00467     interval_type ilow = I->low();
00468     interval_type ihigh = I->high();
00469 
00470     while(1)
00471     {
00472         bool created = false;
00473         if(R == nil) {
00474             IBSNode<ITYPE> *tmp = new IBSNode<ITYPE>(ihigh,nil);
00475             ++treeSize;
00476             created = true;
00477             if(parent == NULL) // must be the root
00478                 root = tmp;
00479             else {
00480                 tmp->parent = parent;
00481                 if(tmp->value() < parent->value())
00482                     parent->left = tmp;
00483                 else if(tmp->value() > parent->value())
00484                     parent->right = tmp;
00485                 else 
00486                     assert(0); // can't get here
00487             }
00488             R = tmp;
00489         }
00490 
00491         interval_type rval = R->value();
00492 
00493         if(rval == ihigh) {
00494             // Case 1. Everything in R's left subtree will be
00495             // within the interval (that is, the nearest ancestor
00496             // node that has R in its right subtree [leftUp(R)]
00497             // has a value equal to or exceeding the low bound of I
00498             //
00499             // NB the upper bound of the interval is open, so don't 
00500             // add to r.equals here. Compare addLeft
00501             if(leftUp(R) >= ilow)
00502                 R->less.insert(I);
00503 
00504             if(created)
00505                 return R; 
00506             else
00507                 return NULL;
00508         }
00509         else if(rval < ihigh) {
00510             if(rval > ilow) {
00511                 // R is in the interval
00512                 R->equal.insert( I ); 
00513             }
00514             if( leftUp(R) >= ilow ) {
00515                 // Everything to the left of R is within the interval
00516                 R->less.insert( I );
00517             }
00518 
00519             parent = R;
00520             R = R->right;
00521             continue;
00522         }
00523         else if(rval > ihigh) {
00524             // R not in the interval
00525             parent = R;
00526             R = R->left;
00527             continue;
00528         }
00529         else {
00530             assert(0);
00531             return NULL;
00532         }
00533     }
00534 
00535     assert(0);
00536     return NULL; // make GCC happy
00537 }
00538 
00539 /* Traverse upward in the tree, looking for the nearest ancestor
00540    that has R in its left subtree and return that value. Since this
00541    routine is used to compute an upper bound on an interval, failure
00542    to find a node should return +infinity */
00543 template<class ITYPE>
00544 typename ITYPE::type
00545 IBSTree<ITYPE>::rightUp(IBSNode<ITYPE> *R)
00546 {
00547     while(NULL != R->parent) {
00548         if(R->parent->left == R)
00549             return R->parent->value();
00550         R = R->parent; 
00551     }
00552     return numeric_limits<interval_type>::max();
00553 }
00554 
00555 /* Same as rightUp, only looking for the nearest ancestor node that
00556    has R in its RIGHT subtree, returning NEGATIVE infinity upon failure */
00557 template<class ITYPE>
00558 typename ITYPE::type
00559 IBSTree<ITYPE>::leftUp(IBSNode<ITYPE> *R)
00560 {
00561     while(NULL != R->parent) {
00562         if(R->parent->right == R)
00563             return R->parent->value();
00564         R = R->parent;
00565     }
00566     // XXX is this right? for unsigned values, min() is a possible value
00567     return numeric_limits<interval_type>::min();
00568 }
00569 
00570 /* Restore RB-tree invariants after node insertion */
00571 template<class ITYPE>
00572 void IBSTree<ITYPE>::insertFixup(IBSNode<ITYPE> *x)
00573 {
00574     x->color = IBS::TREE_RED;
00575     while((x != root) && (x->parent->color == IBS::TREE_RED)) {
00576         if(x->parent == x->parent->parent->left) {
00577             IBSNode<ITYPE>* y = x->parent->parent->right;
00578             if(y->color == IBS::TREE_RED) {
00579                 x->parent->color = IBS::TREE_BLACK;
00580                 y->color = IBS::TREE_BLACK;
00581                 x->parent->parent->color = IBS::TREE_RED;
00582                 x = x->parent->parent;
00583             }
00584             else {
00585                 if(x == x->parent->right) {
00586                     x = x->parent;
00587                     leftRotate(x);
00588                 }
00589                 x->parent->color = IBS::TREE_BLACK;
00590                 x->parent->parent->color = IBS::TREE_RED;
00591                 rightRotate(x->parent->parent);
00592             }
00593         }
00594         else {
00595             IBSNode<ITYPE> *y = x->parent->parent->left;
00596             if(y->color == IBS::TREE_RED) {
00597                 x->parent->color = IBS::TREE_BLACK;
00598                 y->color = IBS::TREE_BLACK;
00599                 x->parent->parent->color = IBS::TREE_RED;
00600                 x = x->parent->parent;
00601             }
00602             else {
00603                 if(x == x->parent->left) {
00604                     x = x->parent;
00605                     rightRotate(x);
00606                 }
00607                 x->parent->color = IBS::TREE_BLACK;
00608                 x->parent->parent->color = IBS::TREE_RED;
00609                 leftRotate(x->parent->parent);
00610             }
00611         }
00612     }
00613     root->color = IBS::TREE_BLACK;
00614 }
00615 
00616 template<class ITYPE>
00617 void IBSTree<ITYPE>::destroy(IBSNode<ITYPE> *n)
00618 {
00619     if(!n || (n == nil))
00620         return;
00621     if(n->left != nil)
00622         destroy(n->left);
00623     if(n->right != nil)
00624         destroy(n->right);
00625     delete n;
00626 }
00627 
00628 
00629 /* void deleteFixup(IBSNode<ITYPE> *)
00630 {
00631     // XXX not implemented
00632     assert(0);
00633 }*/
00634 
00635 template<class ITYPE>
00636 void IBSTree<ITYPE>::findIntervals(interval_type X, IBSNode<ITYPE> *R, set<ITYPE *> &S) const
00637 {
00638     while(R != nil) {
00639         if(X == R->value()) {
00640             S.insert(R->equal.begin(),R->equal.end());
00641             return;
00642         }
00643         else if(X < R->value()) {
00644             S.insert(R->less.begin(),R->less.end());
00645             R = R->left;
00646         } else {
00647             S.insert(R->greater.begin(),R->greater.end());
00648             R = R->right;
00649         }
00650     }
00651 }
00652 
00653 /* Find all intervals that intersect an interval:
00654 
00655    If low is < a node, take the < set (any interval in < contains low)
00656    If low or high are > a node, take the > set
00657    If low <= a node and high > a node, take the = set
00658 
00659    NB Because this traversal may go both directions in the tree,
00660       it remains a recursive operation and is less efficient
00661       than a pointwise stabbing query.
00662 */
00663 template<class ITYPE>
00664 void IBSTree<ITYPE>::findIntervals(ITYPE * I, IBSNode<ITYPE> *R, set<ITYPE *> &S) const
00665 {
00666     if(R == nil) return;
00667 
00668     interval_type low = I->low();
00669     interval_type high = I->high();    
00670 
00671     if(low < R->value()) {
00672         S.insert(R->less.begin(),R->less.end());
00673         findIntervals(I,R->left,S);
00674     }
00675     if(low > R->value() || high > R->value()) {
00676         S.insert(R->greater.begin(),R->greater.end());
00677         findIntervals(I,R->right,S);
00678     }
00679     if(low <= R->value() && high > R->value()) {
00680         S.insert(R->equal.begin(),R->equal.end());
00681     } 
00682     else if(low == R->value() && high == R->value()) {
00683         // XXX explicitly allow zero-length intervals
00684         //     to `match' the starting value
00685         S.insert(R->equal.begin(),R->equal.end());
00686     }
00687 }
00688 
00689 template<class ITYPE>
00690 void IBSTree<ITYPE>::removeInterval(IBSNode<ITYPE> *R, ITYPE *range)
00691 {
00692     if(R == nil) return;
00693 
00694     interval_type low = range->low();
00695     interval_type high = range->high();    
00696 
00697     // FIXME this doesn't use maximality and containment to minimize the
00698     // number of set::erase calls
00699     if(low < R->value()) {
00700         R->less.erase(range);
00701         removeInterval(R->left,range);
00702     }
00703     if(low > R->value() || high > R->value()) {
00704         R->greater.erase(range);
00705         removeInterval(R->right,range);
00706     }
00707     if(low <= R->value() && high > R->value()) {
00708         R->equal.erase(range);
00709     }
00710     else if(low == R->value() && high == R->value()) {
00711         // XXX explicitly allow zero-length intervals
00712         //     to `match' the starting value
00713         R->equal.erase(range);
00714     }
00715 }
00716 
00717 template<class ITYPE>
00718 int IBSTree<ITYPE>::CountMarks(IBSNode<ITYPE> *R) const
00719 {
00720     if(R == nil) return 0;
00721 
00722     return (R->less.size() + R->greater.size() + R->equal.size()) +
00723         CountMarks(R->left) + CountMarks(R->right);
00724 }
00725 
00726 /***************** Public methods *****************/
00727 
00728 template<class ITYPE>
00729 void IBSTree<ITYPE>::insert(ITYPE *range)
00730 {
00731     //stats_.startTimer("insert");
00732 
00733     // Insert the endpoints of the range, rebalancing if new
00734     // nodes were created
00735     IBSNode<ITYPE> *x = addLeft(range,root);
00736     if(x) {
00737         insertFixup(x);
00738     }
00739     x = addRight(range,root);
00740     if(x) {
00741         insertFixup(x);
00742     }
00743 
00744     //stats_.stopTimer("insert");
00745 }
00746 
00747 template<class ITYPE>
00748 void IBSTree<ITYPE>::remove(ITYPE * range)
00749 {
00750     //stats_.startTimer("remove");
00751 
00752     // 1. Remove all interval markers corresponding to range from the tree,
00753     //    using the reverse of the insertion procedure.
00754 
00755     // 2. If no other intervals use the endpoints of this interval
00756     //    (find this how?), remove their endpoints (complex) and fix
00757     //    up the tree.
00758 
00759     // XXX FIXME XXX
00760     // Currently being very lazy and inefficient: only removing interval
00761     // markers (not end nodes even if they end up unused), and also removing
00762     // elements from each of the <, >, and = sets of each node (following
00763     // the tests of the insertion procedures would avoid many of these
00764     // O(log n) lookups
00765 
00766     removeInterval(root,range);
00767    
00768     //stats_.startTimer("remove"); 
00769 }
00770 
00771 template<class ITYPE>
00772 int IBSTree<ITYPE>::find(interval_type X, set<ITYPE *> &out) const
00773 {
00774     unsigned size = out.size();
00775     findIntervals(X,root,out);
00776     return out.size() - size;
00777 }
00778 
00779 template<class ITYPE>
00780 int IBSTree<ITYPE>::find(ITYPE * I, set<ITYPE *> &out) const
00781 {
00782     unsigned size = out.size();
00783     findIntervals(I,root,out);
00784     return out.size() - size;
00785 }
00786 
00787 template<class ITYPE>
00788 void IBSTree<ITYPE>::successor(interval_type X, set<ITYPE *> &out) const
00789 {
00790     IBSNode<ITYPE> *n = root;
00791     IBSNode<ITYPE> *last = nil;
00792 
00793     std::vector< IBSNode<ITYPE>* > stack;
00794 
00795     /* last will hold the node immediately greater than X */
00796     while(1) {
00797         if(n == nil) {
00798             if(last != nil) {
00799                 typename set<ITYPE *>::iterator sit = last->equal.begin();
00800                 for( ; sit != last->equal.end(); ++sit) {
00801                    if((*sit)->low() == last->value()) out.insert(*sit);
00802                 }
00803                 if(!out.empty())
00804                     break;
00805                 else {
00806                     // have missed out. pop back up to the last node where
00807                     // we went left and then advance down its right path
00808                     n = last->right;
00809                     if(!stack.empty()) {
00810                         last = stack.back();
00811                         stack.pop_back();
00812                     } else {
00813                         last = nil;
00814                     }
00815                     continue;
00816                 } 
00817             } else 
00818                 break;
00819         }
00820 
00821         if(X >= n->value()) {
00822             n = n->right;
00823         } else {
00824             if(last != nil)
00825                 stack.push_back(last);
00826             last = n;
00827             n = n->left;
00828         }
00829     }
00830 }
00831 
00832 template<class ITYPE>
00833 ITYPE * IBSTree<ITYPE>::successor(interval_type X) const
00834 {
00835     set<ITYPE *> out;
00836     successor(X,out);
00837     assert( out.size() <= 1 );
00838     if(!out.empty())
00839         return *out.begin();
00840     else
00841         return NULL;
00842 }
00843 
00844 template<class ITYPE>
00845 void IBSTree<ITYPE>::clear() {
00846     if(root == nil) return;
00847     destroy(root);
00848     root = nil;
00849     treeSize = 0;
00850 }
00851 
00852 template<class ITYPE>
00853 int IBSTree<ITYPE>::height(IBSNode<ITYPE> *n)
00854 {
00855     if(!n)
00856         return 0;
00857     
00858     int leftHeight = 1 + height(n->left);
00859     int rightHeight = 1 + height(n->right);
00860 
00861     if(leftHeight > rightHeight)
00862         return leftHeight;
00863     else
00864         return rightHeight;
00865 }
00866 
00867 template<class ITYPE>
00868 void IBSTree<ITYPE>::PrintPreorder(IBSNode<ITYPE> *n)
00869 {
00870     if(n == nil) return;
00871 
00872     PrintPreorder(n->left);
00873     printf(" %d\n",n->value());
00874     PrintPreorder(n->right);
00875 
00876     if(n == root) {
00877         int h = height(root);
00878         printf(" tree height: %d\n", h);
00879     }
00880 }
00881 
00882 template<class ITYPE>
00883 int IBSTree<ITYPE>::CountMarks() const
00884 {
00885     return CountMarks(root);
00886 }
00887 } /* Dyninst */
00888 #endif
00889 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1