avl.hxx

Go to the documentation of this file.
00001 #ifndef UTIL_AVL_HXX
00002 #define UTIL_AVL_HXX
00003 
00004 /*
00005  * Copyright (c) 2004, The EROS Group, LLC and Johns Hopkins
00006  * University. All rights reserved.
00007  * 
00008  * This software was developed to support the EROS secure operating
00009  * system project (http://www.eros-os.org). The latest version of
00010  * the OpenCM software can be found at http://www.opencm.org.
00011  * 
00012  * Redistribution and use in source and binary forms, with or
00013  * without modification, are permitted provided that the following
00014  * conditions are met:
00015  * 
00016  * 1. Redistributions of source code must retain the above copyright
00017  *    notice, this list of conditions and the following disclaimer.
00018  * 
00019  * 2. Redistributions in binary form must reproduce the above
00020  *    copyright notice, this list of conditions and the following
00021  *    disclaimer in the documentation and/or other materials
00022  *    provided with the distribution.
00023  * 
00024  * 3. Neither the name of the The EROS Group, LLC nor the name of
00025  *    Johns Hopkins University, nor the names of its contributors
00026  *    may be used to endorse or promote products derived from this
00027  *    software without specific prior written permission.
00028  * 
00029  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
00030  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
00031  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00032  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00033  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
00034  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00035  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00036  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00037  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00038  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00039  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00040  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00041  * POSSIBILITY OF SUCH DAMAGE.
00042  */
00043 
00044 /* This is mildly tricky, because we really don't want to have to
00045  * polyinstantiate the source code for the whole AVL
00046  * implementation. We therefore divide matters into a generic
00047  * BaseAvlNode structure and a generic BaseAvlTree data structure --
00048  * the latter serves as the container and stores a pointer to the
00049  * comparison routine.
00050  *
00051  * We then use templates to instantiate type-specific avl trees.
00052  */
00053 
00054 // FIX: Following comment needs repair
00055 
00073 class BaseAvlNode {
00074   friend class BaseAvlTree;
00075   BaseAvlNode *lchild;
00076   BaseAvlNode *rchild;
00077   short    balance;             /* legal values are 0, 1, -1 */
00078 
00079   static BaseAvlNode *left_rotate(BaseAvlNode *);
00080   static BaseAvlNode *right_rotate(BaseAvlNode *);
00081   static int rebalance_right(BaseAvlNode ** theRoot);
00082   static int rebalance_left(BaseAvlNode ** theRoot);
00083 
00084  public:
00085   BaseAvlNode();
00086   virtual ~BaseAvlNode();
00087 
00088   unsigned short user;          /* user-available field */
00089 };
00090 
00091 class BaseAvlNode;
00092 
00098 class BaseAvlTree {
00099 protected:
00100   typedef int (*BaseCmpFn_t)(const BaseAvlNode& n1, const BaseAvlNode& n2);
00101 private:
00102   BaseCmpFn_t cmpfn;
00103   BaseAvlNode *root;
00104 
00105   int do_insert(BaseAvlNode **theRoot, BaseAvlNode *nd);
00106   int do_remove(BaseAvlNode **theRoot, BaseAvlNode *nd);
00107 
00108   static BaseAvlNode** find_greatest(BaseAvlNode**pnd);
00109 public:
00110   BaseAvlTree(BaseCmpFn_t cmp);
00111   ~BaseAvlTree();
00112 
00113 protected:
00117   void insert(BaseAvlNode *nd);
00118 
00122   BaseAvlNode *choose();
00123 
00126   BaseAvlNode *least();
00127 
00130   BaseAvlNode *greatest();
00131 
00137   void remove(BaseAvlNode& node);
00138 
00152   BaseAvlNode *lookup(const BaseAvlNode& key);
00153 
00157   BaseAvlNode *lookupGLE(const BaseAvlNode& key);
00158 
00159   /* When iterating over an AvlTree, this function is called on every
00160      node. If it returns zero, no attempt will be made to reinsert the
00161      node into the tree, and the called procedure should free the occupied
00162      storage. */
00163   typedef int (*AvlIterFunc)(BaseAvlNode&);
00164 
00165   /* calls avlFunc on every node in a tree */
00166   void iterate(AvlIterFunc avlFunc);
00167 };
00168 
00169 // Forward declaration:
00170 template<typename KeyType> class AvlTree;
00171 
00172 template<typename KeyType>
00173 class AvlNode : public BaseAvlNode {
00174   friend class AvlTree<KeyType>;
00175 
00176  public:
00177   KeyType key;
00178 
00179   AvlNode(KeyType k)
00180     : key(k)
00181   {
00182   }
00183   ~AvlNode()
00184   {
00185   }
00186 
00187 protected:
00188   inline static int compare(const AvlNode& n1, const AvlNode& n2)
00189   {
00190       if (n1.key < n2.key)
00191         return -1;
00192       if (n1.key > n2.key)
00193         return 1;
00194       return 0;
00195   }
00196 };
00197 
00198 // Forward declaration
00199 template<typename KeyType, typename ValueType> class AvlMap;
00200 
00201 template<typename KeyType, typename ValueType>
00202 class AvlMapNode : public AvlNode<KeyType> {
00203   friend class AvlMap<KeyType, ValueType>;
00204 
00205  public:
00206   ValueType value;
00207 
00208   AvlMapNode(KeyType k, ValueType v)
00209     : AvlNode<KeyType>(k), value(v)
00210   {
00211   }
00212   ~AvlMapNode()
00213   {
00214   }
00215 };
00216 
00217 template<typename KeyType>
00218 class AvlTree : public BaseAvlTree {
00219   typedef AvlNode<KeyType> NodeType;
00220   typedef AvlNode<KeyType> KeyNodeType;
00221  public:
00222   AvlTree()
00223     : BaseAvlTree((BaseCmpFn_t) AvlNode<KeyType>::compare)
00224     {
00225     }
00226   ~AvlTree()
00227     {
00228     }
00229 
00233   inline void insert(const KeyType& key)
00234     {
00235       BaseAvlNode::insert(new NodeType(key));
00236     }
00237 
00241   inline NodeType *choose()
00242     {
00243       return (NodeType *) BaseAvlNode::choose();
00244     }
00245 
00248   inline NodeType *least()
00249     {
00250       return (NodeType *) BaseAvlNode::least();
00251     }
00252 
00255   inline NodeType *greatest()
00256     {
00257       return (NodeType *) BaseAvlNode::greatest();
00258     }
00259 
00263   inline void remove(NodeType &node)
00264     {
00265       BaseAvlNode::remove(node);
00266     }
00267 
00281   inline NodeType *lookup(const KeyNodeType& key)
00282     {
00283       return (NodeType *)BaseAvlNode::lookup(key);
00284     }
00285   inline NodeType *lookup(KeyType key)
00286     {
00287       return lookup(NodeType(key));
00288     }
00289 
00293   inline NodeType *lookupGLE(const NodeType& key)
00294     {
00295       return (NodeType *)BaseAvlNode::lookupGLE(key);
00296     }
00297   inline NodeType *lookupGLE(KeyType key)
00298     {
00299       return lookupGLE(NodeType(key));
00300     }
00301 
00302   /* When iterating over an AvlTree, this function is called on every
00303      node. If it returns zero, no attempt will be made to reinsert the
00304      node into the tree, and the called procedure should free the occupied
00305      storage. */
00306   typedef int (*AvlIterFunc)(NodeType*);
00307 
00308   /* calls avlFunc on every node in a tree */
00309   inline void iterate(AvlIterFunc avlFunc)
00310     {
00311       BaseAvlTree::iterate(avlFunc);
00312     }
00313 };
00314 
00315 template<typename KeyType, typename ValueType>
00316 class AvlMap : public BaseAvlTree {
00317  public:
00318   typedef AvlMapNode<KeyType, ValueType> NodeType;
00319   typedef AvlNode<KeyType> KeyNodeType;
00320 
00321   AvlMap()
00322     : BaseAvlTree((BaseCmpFn_t) AvlMapNode<KeyType,ValueType>::compare)
00323     {
00324     }
00325   ~AvlMap()
00326     {
00327     }
00328 
00329   bool contains(const KeyType& key)
00330   {
00331     return lookup(key) ? true : false;
00332   }
00333 
00337   inline void insert(const KeyType& key, const ValueType& v)
00338     {
00339       BaseAvlTree::insert(new NodeType(key,v));
00340     }
00341 
00345   inline NodeType *choose()
00346     {
00347       return (NodeType *) BaseAvlTree::choose();
00348     }
00349 
00352   inline NodeType *least()
00353     {
00354       return (NodeType *) BaseAvlTree::least();
00355     }
00356 
00359   inline NodeType *greatest()
00360     {
00361       return (NodeType *) BaseAvlTree::greatest();
00362     }
00363 
00367   inline void remove(NodeType &node)
00368     {
00369       BaseAvlTree::remove(node);
00370     }
00371 
00372 #if 0
00373   inline void removeByKey(const KeyType& key)
00374     {
00375       NodeType *nd = lookup(key);
00376       if (!nd)
00377         THROW(ExBadValue, "Key not in map");
00378       BaseAvlTree::remove(*nd);
00379     }
00380 #endif
00381 
00395   inline NodeType *lookup(const KeyNodeType& key)
00396     {
00397       return (NodeType *)BaseAvlTree::lookup(key);
00398     }
00399   inline NodeType *lookup(const KeyType& key)
00400     {
00401       return lookup(KeyNodeType(key));
00402     }
00403 
00407   inline NodeType *lookupGLE(const NodeType& key)
00408     {
00409       return (NodeType *)BaseAvlTree::lookupGLE(key);
00410     }
00411   inline NodeType *lookupGLE(KeyType key)
00412     {
00413       return lookupGLE(NodeType(key));
00414     }
00415 
00416   /* When iterating over an AvlMap, this function is called on every
00417      node. If it returns zero, no attempt will be made to reinsert the
00418      node into the tree, and the called procedure should free the occupied
00419      storage. */
00420   typedef int (*AvlIterFunc)(NodeType*);
00421 
00422   /* calls avlFunc on every node in a tree */
00423   inline void iterate(AvlIterFunc avlFunc)
00424     {
00425       BaseAvlTree::iterate(avlFunc);
00426     }
00427 };
00428 
00429 template<typename KeyType>
00430 struct AvlSet : public AvlMap<KeyType, bool> {
00431   typedef AvlMapNode<KeyType, bool> NodeType;
00432 
00433   void insert(const KeyType& key)
00434   {
00435     if (!contains(key))
00436       AvlMap<KeyType, bool>::insert(key, true);
00437   }
00438 
00439   void remove(const KeyType& key)
00440   {
00441     NodeType *nd = lookup(key);
00442     if (!nd)
00443       THROW(ExBadValue, "Key not in set");
00444     AvlMap<KeyType, bool>::remove(*nd);
00445   }
00446 };
00447 
00448 // Local Variables:
00449 // mode:c++
00450 // End:
00451 
00452 #endif /* UTIL_AVL_HXX */

Generated on Sun Apr 23 22:42:34 2006 for OpenCM by  doxygen 1.4.6