Main Page   Class Hierarchy   Compound List   File List   Compound Members   Related Pages  

eavlmmap.h

00001 //
00002 // eavlmmap.h --- definition for embedded avl multimap class
00003 //
00004 // Copyright (C) 1996 Limit Point Systems, Inc.
00005 //
00006 // Author: Curtis Janssen <cljanss@limitpt.com>
00007 // Maintainer: LPS
00008 //
00009 // This file is part of the SC Toolkit.
00010 //
00011 // The SC Toolkit is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Library General Public License as published by
00013 // the Free Software Foundation; either version 2, or (at your option)
00014 // any later version.
00015 //
00016 // The SC Toolkit is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU Library General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Library General Public License
00022 // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
00023 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
00024 //
00025 // The U.S. Government is granted a limited license as per AL 91-7.
00026 //
00027 
00028 #ifndef _util_container_eavlmmap_h
00029 #define _util_container_eavlmmap_h
00030 
00031 #ifdef HAVE_CONFIG_H
00032 #  include <scconfig.h>
00033 #endif
00034 #include <iostream>
00035 #include <util/misc/exenv.h>
00036 #include <util/container/compare.h>
00037 #include <unistd.h> // for size_t on solaris
00038 #include <stdlib.h>
00039 
00040 #ifdef __GNUC__
00041 // gcc typename seems to be broken in some cases
00042 #  define eavl_typename
00043 #else
00044 #  define eavl_typename typename
00045 #endif
00046 
00047 template <class K, class T>
00048 class EAVLMMapNode {
00049   public:
00050     K key;
00051     T* lt;
00052     T* rt;
00053     T* up;
00054     int balance;
00055   public:
00056     EAVLMMapNode(const K& k): key(k) {}
00057 };
00058 
00059 template <class K, class T>
00060 class EAVLMMap {
00061   private:
00062     size_t length_;
00063     T *root_;
00064     T *start_;
00065     EAVLMMapNode<K,T> T::* node_;
00066   public:
00067 #if defined(__GNUC__) && defined(__alpha__)
00068     T*& rlink(const T* n) const { T*& r = (n->*node_).rt; return r; }
00069     T*& llink(const T* n) const { T*& r = (n->*node_).lt; return r; }
00070     T*& uplink(const T* n) const { T*& r = (n->*node_).up; return r; }
00071     int& balance(const T* n) const { int& r = (n->*node_).balance; return r; }
00072     K& key(T* n) const { K& r = (n->*node_).key; return r; }
00073     const K& key(const T* n) const { K& r = (n->*node_).key; return r; }
00074 #else    
00075     T*& rlink(T* n) const { return (n->*node_).rt; }
00076     T* rlink(const T* n) const { return (n->*node_).rt; }
00077     T*& llink(T* n) const { return (n->*node_).lt; }
00078     T* llink(const T* n) const { return (n->*node_).lt; }
00079     T*& uplink(T* n) const { return (n->*node_).up; }
00080     T* uplink(const T* n) const { return (n->*node_).up; }
00081     int& balance(T* n) const { return (n->*node_).balance; }
00082     int balance(const T* n) const { return (n->*node_).balance; }
00083     K& key(T* n) const { return (n->*node_).key; }
00084     const K& key(const T* n) const { return (n->*node_).key; }
00085 #endif
00086     int compare(T*n,T*m) const { return ::compare(key(n), key(m)); }
00087     int compare(T*n,const K&m) const { return ::compare(key(n), m); }
00088   private:
00089     void adjust_balance_insert(T* A, T* child);
00090     void adjust_balance_remove(T* A, T* child);
00091     void clear(T*);
00092   public:
00093     class iterator {
00094       private:
00095         EAVLMMap<K,T> *map_;
00096         T *node;
00097       public:
00098         iterator(EAVLMMap<K,T> *m, T *n):map_(m),node(n){}
00099         iterator(const eavl_typename EAVLMMap<K,T>::iterator &i) { map_=i.map_; node=i.node; }
00100         void operator++() { map_->next(node); }
00101         void operator++(int) { operator++(); }
00102         int operator == (const eavl_typename EAVLMMap<K,T>::iterator &i) const
00103             { return map_ == i.map_ && node == i.node; }
00104         int operator != (const eavl_typename EAVLMMap<K,T>::iterator &i) const
00105             { return !operator == (i); }
00106         void operator = (const eavl_typename EAVLMMap<K,T>::iterator &i)
00107             { map_ = i.map_; node = i.node; }
00108         const K &key() const { return map_->key(node); }
00109         T & operator *() { return *node; }
00110         T * operator->() { return node; }
00111     };
00112   public:
00113     EAVLMMap();
00114     EAVLMMap(EAVLMMapNode<K,T> T::* node);
00115     ~EAVLMMap() { clear(root_); }
00116     void initialize(EAVLMMapNode<K,T> T::* node);
00117     void clear_without_delete() { initialize(node_); }
00118     void clear() { clear(root_); initialize(node_); }
00119     void insert(T*);
00120     void remove(T*);
00121     T* find(const K&) const;
00122 
00123     int height(T* node);
00124     int height() { return height(root_); }
00125     void check();
00126     void check_node(T*) const;
00127 
00128     T* start() const { return start_; }
00129     void next(const T*&) const;
00130     void next(T*&) const;
00131 
00132     iterator begin() { return iterator(this,start()); }
00133     iterator end() { return iterator(this,0); }
00134 
00135     void print();
00136     int length() const { return length_; }
00137     int depth(T*);
00138 };
00139 
00140 template <class K, class T>
00141 T*
00142 EAVLMMap<K,T>::find(const K& key) const
00143 {
00144   T* n = root_;
00145 
00146   while (n) {
00147       int cmp = compare(n, key);
00148       if (cmp < 0) n = rlink(n);
00149       else if (cmp > 0) n = llink(n);
00150       else return n;
00151     }
00152 
00153   return 0;
00154 }
00155 
00156 template <class K, class T>
00157 void
00158 EAVLMMap<K,T>::remove(T* node)
00159 {
00160   if (!node) return;
00161 
00162   length_--;
00163 
00164   if (node == start_) {
00165       next(start_);
00166     }
00167 
00168   T *rebalance_point;
00169   T *q;
00170 
00171   if (llink(node) == 0) {
00172       q = rlink(node);
00173       rebalance_point = uplink(node);
00174 
00175       if (q) uplink(q) = rebalance_point;
00176 
00177       if (rebalance_point) {
00178           if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
00179           else llink(rebalance_point) = q;
00180         }
00181       else root_ = q;
00182     }
00183   else if (rlink(node) == 0) {
00184       q = llink(node);
00185       rebalance_point = uplink(node);
00186 
00187       if (q) uplink(q) = rebalance_point;
00188 
00189       if (rebalance_point) {
00190           if (rlink(rebalance_point) == node) rlink(rebalance_point) = q;
00191           else llink(rebalance_point) = q;
00192         }
00193       else root_ = q;
00194     }
00195   else {
00196       T *r = node;
00197       next(r);
00198 
00199       if (r == 0 || llink(r) != 0) {
00200           ExEnv::err() << "EAVLMMap::remove: inconsistency" << std::endl;
00201           abort();
00202         }
00203 
00204       if (r == rlink(node)) {
00205           llink(r) = llink(node);
00206           if (llink(r)) uplink(llink(r)) = r;
00207           balance(r) = balance(node);
00208           rebalance_point = r;
00209           q = rlink(r);
00210         }
00211       else {
00212           q = rlink(r);
00213 
00214           rebalance_point = uplink(r);
00215 
00216           if (llink(rebalance_point) == r) llink(rebalance_point) = q;
00217           else rlink(rebalance_point) = q;
00218 
00219           if (q) uplink(q) = rebalance_point;
00220 
00221           balance(r) = balance(node);
00222           rlink(r) = rlink(node);
00223           llink(r) = llink(node);
00224           if (rlink(r)) uplink(rlink(r)) = r;
00225           if (llink(r)) uplink(llink(r)) = r;
00226         }
00227       if (r) {
00228           T* up = uplink(node);
00229           uplink(r) = up;
00230           if (up) {
00231               if (rlink(up) == node) rlink(up) = r;
00232               else llink(up) = r;
00233             }
00234           if (up == 0) root_ = r;
00235         }
00236     }
00237 
00238   // adjust balance won't work if both children are null,
00239   // so handle this special case here
00240   if (rebalance_point &&
00241       llink(rebalance_point) == 0 && rlink(rebalance_point) == 0) {
00242       balance(rebalance_point) = 0;
00243       q = rebalance_point;
00244       rebalance_point = uplink(rebalance_point);
00245     }
00246   adjust_balance_remove(rebalance_point, q);
00247 }
00248 
00249 template <class K, class T>
00250 void
00251 EAVLMMap<K,T>::print()
00252 {
00253   for (T*n=start(); n; next(n)) {
00254       int d = depth(n) + 1;
00255       for (int i=0; i<d; i++) ExEnv::out() << "     ";
00256       if (balance(n) == 1) ExEnv::out() << " (+)" << std::endl;
00257       else if (balance(n) == -1) ExEnv::out() << " (-)" << std::endl;
00258       else if (balance(n) == 0) ExEnv::out() << " (.)" << std::endl;
00259       else ExEnv::out() << " (" << balance(n) << ")" << std::endl;
00260     }
00261 }
00262 
00263 template <class K, class T>
00264 int
00265 EAVLMMap<K,T>::depth(T*node)
00266 {
00267   int d = 0;
00268   while (node) {
00269       node = uplink(node);
00270       d++;
00271     }
00272   return d;
00273 }
00274 
00275 template <class K, class T>
00276 void
00277 EAVLMMap<K,T>::check_node(T*n) const
00278 {
00279   if (uplink(n) && uplink(n) == n) abort();
00280   if (llink(n) && llink(n) == n) abort();
00281   if (rlink(n) && rlink(n) == n) abort();
00282   if (rlink(n) && rlink(n) == llink(n)) abort();
00283   if (uplink(n) && uplink(n) == llink(n)) abort();
00284   if (uplink(n) && uplink(n) == rlink(n)) abort();
00285   if (uplink(n) && !(llink(uplink(n)) == n
00286                      || rlink(uplink(n)) == n)) abort();
00287 }
00288 
00289 template <class K, class T>
00290 void
00291 EAVLMMap<K,T>::clear(T*n)
00292 {
00293   if (!n) return;
00294   clear(llink(n));
00295   clear(rlink(n));
00296   delete n;
00297 }
00298 
00299 template <class K, class T>
00300 int
00301 EAVLMMap<K,T>::height(T* node)
00302 {
00303   if (!node) return 0;
00304   int rh = height(rlink(node)) + 1;
00305   int lh = height(llink(node)) + 1;
00306   return rh>lh?rh:lh;
00307 }
00308 
00309 template <class K, class T>
00310 void
00311 EAVLMMap<K,T>::check()
00312 {
00313   T* node;
00314   T* prev=0;
00315   size_t computed_length = 0;
00316   for (node = start(); node; next(node)) {
00317       check_node(node);
00318       if (prev && compare(prev,node) > 0) {
00319           ExEnv::err() << "nodes out of order" << std::endl;
00320           abort();
00321         }
00322       prev = node;
00323       computed_length++;
00324     }
00325   for (node = start(); node; next(node)) {
00326       if (balance(node) != height(rlink(node)) - height(llink(node))) {
00327           ExEnv::err() << "balance inconsistency" << std::endl;
00328           abort();
00329         }
00330       if (balance(node) < -1 || balance(node) > 1) {
00331           ExEnv::err() << "balance out of range" << std::endl;
00332           abort();
00333         }
00334     }
00335   if (length_ != computed_length) {
00336       ExEnv::err() << "length error" << std::endl;
00337       abort();
00338     }
00339 }
00340 
00341 template <class K, class T>
00342 void
00343 EAVLMMap<K,T>::next(const T*& node) const
00344 {
00345   const T* r;
00346   if (r = rlink(node)) {
00347       node = r;
00348       while (r = llink(node)) node = r;
00349       return;
00350     }
00351   while (r = uplink(node)) {
00352       if (node == llink(r)) {
00353           node = r;
00354           return;
00355         }
00356       node = r;
00357     }
00358   node = 0;
00359 }
00360 
00361 template <class K, class T>
00362 void
00363 EAVLMMap<K,T>::next(T*& node) const
00364 {
00365   T* r;
00366   if (r = rlink(node)) {
00367       node = r;
00368       while (r = llink(node)) node = r;
00369       return;
00370     }
00371   while (r = uplink(node)) {
00372       if (node == llink(r)) {
00373           node = r;
00374           return;
00375         }
00376       node = r;
00377     }
00378   node = 0;
00379 }
00380 
00381 template <class K, class T>
00382 void
00383 EAVLMMap<K,T>::insert(T* n)
00384 {
00385   if (!n) {
00386       return;
00387     }
00388 
00389   length_++;
00390 
00391   rlink(n) = 0;
00392   llink(n) = 0;
00393   balance(n) = 0;
00394 
00395   if (!root_) {
00396       uplink(n) = 0;
00397       root_ = n;
00398       start_ = n;
00399       return;
00400     }
00401 
00402   // find an insertion point
00403   T* p = root_;
00404   T* prev_p = 0;
00405   int cmp;
00406   int have_start = 1;
00407   while (p) {
00408       if (p == n) {
00409           abort();
00410         }
00411       prev_p = p;
00412       cmp = compare(n,p);
00413       if (cmp < 0) p = llink(p);
00414       else {
00415           p = rlink(p);
00416           have_start = 0;
00417         }
00418     }
00419 
00420   // insert the node
00421   uplink(n) = prev_p;
00422   if (prev_p) {
00423       if (cmp < 0) llink(prev_p) = n;
00424       else rlink(prev_p) = n;
00425     }
00426 
00427   // maybe update the first node in the map
00428   if (have_start) start_ = n;
00429 
00430   // adjust the balance factors
00431   if (prev_p) {
00432       adjust_balance_insert(prev_p, n);
00433     }
00434 }
00435 
00436 template <class K, class T>
00437 void
00438 EAVLMMap<K,T>::adjust_balance_insert(T* A, T* child)
00439 {
00440   if (!A) return;
00441   int adjustment;
00442   if (llink(A) == child) adjustment = -1;
00443   else adjustment = 1;
00444   int bal = balance(A) + adjustment;
00445   if (bal == 0) {
00446       balance(A) = 0;
00447     }
00448   else if (bal == -1 || bal == 1) {
00449       balance(A) = bal;
00450       adjust_balance_insert(uplink(A), A);
00451     }
00452   else if (bal == 2) {
00453       T* B = rlink(A);
00454       if (balance(B) == 1) {
00455           balance(B) = 0;
00456           balance(A) = 0;
00457           rlink(A) = llink(B);
00458           llink(B) = A;
00459           uplink(B) = uplink(A);
00460           uplink(A) = B;
00461           if (rlink(A)) uplink(rlink(A)) = A;
00462           if (llink(B)) uplink(llink(B)) = B;
00463           if (uplink(B) == 0) root_ = B;
00464           else {
00465               if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
00466               else llink(uplink(B)) = B;
00467             }
00468         }
00469       else {
00470           T* X = llink(B);
00471           rlink(A) = llink(X);
00472           llink(B) = rlink(X);
00473           llink(X) = A;
00474           rlink(X) = B;
00475           if (balance(X) == 1) {
00476               balance(A) = -1;
00477               balance(B) = 0;
00478             }
00479           else if (balance(X) == -1) {
00480               balance(A) = 0;
00481               balance(B) = 1;
00482             }
00483           else {
00484               balance(A) = 0;
00485               balance(B) = 0;
00486             }
00487           balance(X) = 0;
00488           uplink(X) = uplink(A);
00489           uplink(A) = X;
00490           uplink(B) = X;
00491           if (rlink(A)) uplink(rlink(A)) = A;
00492           if (llink(B)) uplink(llink(B)) = B;
00493           if (uplink(X) == 0) root_ = X;
00494           else {
00495               if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
00496               else llink(uplink(X)) = X;
00497             }
00498         }
00499     }
00500   else if (bal == -2) {
00501       T* B = llink(A);
00502       if (balance(B) == -1) {
00503           balance(B) = 0;
00504           balance(A) = 0;
00505           llink(A) = rlink(B);
00506           rlink(B) = A;
00507           uplink(B) = uplink(A);
00508           uplink(A) = B;
00509           if (llink(A)) uplink(llink(A)) = A;
00510           if (rlink(B)) uplink(rlink(B)) = B;
00511           if (uplink(B) == 0) root_ = B;
00512           else {
00513               if (llink(uplink(B)) == A) llink(uplink(B)) = B;
00514               else rlink(uplink(B)) = B;
00515             }
00516         }
00517       else {
00518           T* X = rlink(B);
00519           llink(A) = rlink(X);
00520           rlink(B) = llink(X);
00521           rlink(X) = A;
00522           llink(X) = B;
00523           if (balance(X) == -1) {
00524               balance(A) = 1;
00525               balance(B) = 0;
00526             }
00527           else if (balance(X) == 1) {
00528               balance(A) = 0;
00529               balance(B) = -1;
00530             }
00531           else {
00532               balance(A) = 0;
00533               balance(B) = 0;
00534             }
00535           balance(X) = 0;
00536           uplink(X) = uplink(A);
00537           uplink(A) = X;
00538           uplink(B) = X;
00539           if (llink(A)) uplink(llink(A)) = A;
00540           if (rlink(B)) uplink(rlink(B)) = B;
00541           if (uplink(X) == 0) root_ = X;
00542           else {
00543               if (llink(uplink(X)) == A) llink(uplink(X)) = X;
00544               else rlink(uplink(X)) = X;
00545             }
00546         }
00547     }
00548 }
00549 
00550 template <class K, class T>
00551 void
00552 EAVLMMap<K,T>::adjust_balance_remove(T* A, T* child)
00553 {
00554   if (!A) return;
00555   int adjustment;
00556   if (llink(A) == child) adjustment = 1;
00557   else adjustment = -1;
00558   int bal = balance(A) + adjustment;
00559   if (bal == 0) {
00560       balance(A) = 0;
00561       adjust_balance_remove(uplink(A), A);
00562     }
00563   else if (bal == -1 || bal == 1) {
00564       balance(A) = bal;
00565     }
00566   else if (bal == 2) {
00567       T* B = rlink(A);
00568       if (balance(B) == 0) {
00569           balance(B) = -1;
00570           balance(A) = 1;
00571           rlink(A) = llink(B);
00572           llink(B) = A;
00573           uplink(B) = uplink(A);
00574           uplink(A) = B;
00575           if (rlink(A)) uplink(rlink(A)) = A;
00576           if (llink(B)) uplink(llink(B)) = B;
00577           if (uplink(B) == 0) root_ = B;
00578           else {
00579               if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
00580               else llink(uplink(B)) = B;
00581             }
00582         }
00583       else if (balance(B) == 1) {
00584           balance(B) = 0;
00585           balance(A) = 0;
00586           rlink(A) = llink(B);
00587           llink(B) = A;
00588           uplink(B) = uplink(A);
00589           uplink(A) = B;
00590           if (rlink(A)) uplink(rlink(A)) = A;
00591           if (llink(B)) uplink(llink(B)) = B;
00592           if (uplink(B) == 0) root_ = B;
00593           else {
00594               if (rlink(uplink(B)) == A) rlink(uplink(B)) = B;
00595               else llink(uplink(B)) = B;
00596             }
00597           adjust_balance_remove(uplink(B), B);
00598         }
00599       else {
00600           T* X = llink(B);
00601           rlink(A) = llink(X);
00602           llink(B) = rlink(X);
00603           llink(X) = A;
00604           rlink(X) = B;
00605           if (balance(X) == 0) {
00606               balance(A) = 0;
00607               balance(B) = 0;
00608             }
00609           else if (balance(X) == 1) {
00610               balance(A) = -1;
00611               balance(B) = 0;
00612             }
00613           else {
00614               balance(A) = 0;
00615               balance(B) = 1;
00616             }
00617           balance(X) = 0;
00618           uplink(X) = uplink(A);
00619           uplink(A) = X;
00620           uplink(B) = X;
00621           if (rlink(A)) uplink(rlink(A)) = A;
00622           if (llink(B)) uplink(llink(B)) = B;
00623           if (uplink(X) == 0) root_ = X;
00624           else {
00625               if (rlink(uplink(X)) == A) rlink(uplink(X)) = X;
00626               else llink(uplink(X)) = X;
00627             }
00628           adjust_balance_remove(uplink(X), X);
00629         }
00630     }
00631   else if (bal == -2) {
00632       T* B = llink(A);
00633       if (balance(B) == 0) {
00634           balance(B) = 1;
00635           balance(A) = -1;
00636           llink(A) = rlink(B);
00637           rlink(B) = A;
00638           uplink(B) = uplink(A);
00639           uplink(A) = B;
00640           if (llink(A)) uplink(llink(A)) = A;
00641           if (rlink(B)) uplink(rlink(B)) = B;
00642           if (uplink(B) == 0) root_ = B;
00643           else {
00644               if (llink(uplink(B)) == A) llink(uplink(B)) = B;
00645               else rlink(uplink(B)) = B;
00646             }
00647         }
00648       else if (balance(B) == -1) {
00649           balance(B) = 0;
00650           balance(A) = 0;
00651           llink(A) = rlink(B);
00652           rlink(B) = A;
00653           uplink(B) = uplink(A);
00654           uplink(A) = B;
00655           if (llink(A)) uplink(llink(A)) = A;
00656           if (rlink(B)) uplink(rlink(B)) = B;
00657           if (uplink(B) == 0) root_ = B;
00658           else {
00659               if (llink(uplink(B)) == A) llink(uplink(B)) = B;
00660               else rlink(uplink(B)) = B;
00661             }
00662           adjust_balance_remove(uplink(B), B);
00663         }
00664       else {
00665           T* X = rlink(B);
00666           llink(A) = rlink(X);
00667           rlink(B) = llink(X);
00668           rlink(X) = A;
00669           llink(X) = B;
00670           if (balance(X) == 0) {
00671               balance(A) = 0;
00672               balance(B) = 0;
00673             }
00674           else if (balance(X) == -1) {
00675               balance(A) = 1;
00676               balance(B) = 0;
00677             }
00678           else {
00679               balance(A) = 0;
00680               balance(B) = -1;
00681             }
00682           balance(X) = 0;
00683           uplink(X) = uplink(A);
00684           uplink(A) = X;
00685           uplink(B) = X;
00686           if (llink(A)) uplink(llink(A)) = A;
00687           if (rlink(B)) uplink(rlink(B)) = B;
00688           if (uplink(X) == 0) root_ = X;
00689           else {
00690               if (llink(uplink(X)) == A) llink(uplink(X)) = X;
00691               else rlink(uplink(X)) = X;
00692             }
00693           adjust_balance_remove(uplink(X), X);
00694         }
00695     }
00696 }
00697 
00698 template <class K, class T>
00699 inline
00700 EAVLMMap<K,T>::EAVLMMap()
00701 {
00702   initialize(0);
00703 }
00704 
00705 template <class K, class T>
00706 inline
00707 EAVLMMap<K,T>::EAVLMMap(EAVLMMapNode<K,T> T::* node)
00708 {
00709   initialize(node);
00710 }
00711 
00712 template <class K, class T>
00713 inline void
00714 EAVLMMap<K,T>::initialize(EAVLMMapNode<K,T> T::* node)
00715 {
00716   node_ = node;
00717   root_ = 0;
00718   start_ = 0;
00719   length_ = 0;
00720 }
00721 
00722 #endif
00723 
00724 // ///////////////////////////////////////////////////////////////////////////
00725 
00726 // Local Variables:
00727 // mode: c++
00728 // c-file-style: "CLJ"
00729 // End:

Generated at Thu Oct 4 18:08:43 2001 for MPQC 2.0.0 using the documentation package Doxygen 1.2.5.