Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

MNdictionary.h

Go to the documentation of this file.
00001 /* Copyright (C) 2000 KOM/Darmstadt University of Technology 00002 * 00003 * You are allowed to use all other parts of the code under the following terms: 00004 * 00005 * For non-commercial use, code may be used in unmodified form provided 00006 * that this copyright notice and this permission notice appear in 00007 * supporting documentation. 00008 * 00009 * This software is provided "as is" and without any express or implied 00010 * warranties, including, without limitation, the implied warranty of 00011 * fitness for a particular purpose. 00012 * 00013 * The code may be subjected to the GNU General Public License, Version 2, 00014 * and re-distributed under the terms of this license. 00015 * As a special exception, permission is granted to link this code 00016 * with the Qt library and distribute executables, as long as you 00017 * follow the requirements of the GNU GPL in regard to all of the 00018 * software in the executable aside from Qt. 00019 * 00020 * Commercial use other than under the terms of the GNU General Public 00021 * License is allowed only after express negotiation of conditions 00022 * with the authors. 00023 */ 00024 #ifndef _MNDICTIONARY_H 00025 #define _MNDICTIONARY_H 1 00026 00027 #include "dict_both.h" 00028 #include <assert.h> 00029 #include <stdlib.h> 00030 #include <time.h> 00031 00032 #include "MNString.h" 00033 00034 /*********************************************************************** 00035 * MNdictionary<K,I> 00036 * 00037 * An alternative MNdictionary template based on AB trees. 00038 * This one has a static member compare() function. The user is forced 00039 * to implement this function 00040 ***********************************************************************/ 00041 00042 template <class K, class I> class MNdictionary 00043 { 00044 // type definitions 00045 private: 00046 typedef _d_dic_item<K,I>* DI; 00047 00048 // member variables 00049 private: 00050 int _size; 00051 DI _root; 00052 00053 // constructors and destructor 00054 public: 00055 MNdictionary (){ 00056 _size = 0; 00057 _root = NULL; 00058 srand((unsigned int) time(NULL)); 00059 } 00060 virtual ~MNdictionary () { 00061 clear(); 00062 } 00063 00064 virtual int compare (const K& x, const K& y) const = 0; 00065 00066 int compare_int( const int& x, const int& y ) const { 00067 return ( (x<y) ? -1 : ( (x>y) ? 1 : 0 ) ); 00068 } 00069 00070 // member functions 00071 public: 00072 K key (const void* it) const; 00073 I inf (const void* it) const; 00074 I& operator[] (const void* it) const; 00075 void* insert (const K& k, const I& i); 00076 void* lookup (const K& k) const; 00077 I access (const K& k) const; 00078 void del (const K& k); 00079 void del_item (const void* it); 00080 void change_inf (const void* it, const I& i); 00081 void clear (); 00082 int size () const; 00083 bool empty () const; 00084 void* first_item ( void* start = NULL ) const; 00085 void* last_item () const; 00086 void* next_item (const void* it) const; 00087 private: 00088 void clear_helper (DI it); 00089 DI pos_finder (const K& k) const; 00090 void rotation (DI it); 00091 }; 00092 00095 00096 template<class K, class I> 00097 inline void* MNdictionary<K,I>::first_item ( void* start ) const { 00098 DI lastit = NULL; 00099 DI it = (start == NULL) ? _root : (DI)start; 00100 while (it != NULL) { 00101 lastit = it; 00102 it = it->left; 00103 } 00104 return (void*)lastit; 00105 } 00106 00107 template<class K, class I> 00108 inline void* MNdictionary<K,I>::last_item () const { 00109 DI lastit = NULL; 00110 DI it = _root; 00111 while (it != NULL) { 00112 lastit = it; 00113 it = it->right; 00114 } 00115 return (void*)lastit; 00116 } 00117 00118 template<class K, class I> 00119 inline K MNdictionary<K,I>::key (const void* it) const { 00120 return ((DI)it)->key; 00121 } 00122 00123 template<class K, class I> 00124 inline I MNdictionary<K,I>::inf (const void* it) const { 00125 return ((DI)it)->inf; 00126 } 00127 00128 template<class K, class I> 00129 inline I& MNdictionary<K,I>::operator[] (const void* it) const { 00130 return (((DI)it)->inf); 00131 } 00132 00133 template<class K, class I> 00134 inline void* MNdictionary<K,I>::lookup (const K& k) const { 00135 if (_root == NULL) return NULL; 00136 else { 00137 DI it = pos_finder(k); 00138 return (compare(it->key, k) == 0) ? (void*)it : NULL; 00139 } 00140 } 00141 00142 template<class K, class I> 00143 inline I MNdictionary<K,I>::access (const K& k) const { 00144 return inf(lookup(k)); 00145 } 00146 00147 template<class K, class I> 00148 inline void MNdictionary<K,I>::del (const K& k) { 00149 void* it = lookup(k); 00150 if (it != NULL) del_item(it); 00151 } 00152 00153 template<class K, class I> 00154 inline void MNdictionary<K,I>::change_inf (const void* it, const I& i) { 00155 ((DI)it)->inf = i; 00156 } 00157 00158 template<class K, class I> 00159 inline void MNdictionary<K,I>::clear () { 00160 if (_root != NULL) { 00161 clear_helper(_root); 00162 _root = NULL; 00163 } 00164 assert(empty()); 00165 } 00166 00167 template<class K, class I> 00168 inline int MNdictionary<K,I>::size () const { 00169 return _size; 00170 } 00171 00172 template<class K, class I> 00173 inline bool MNdictionary<K,I>::empty () const { 00174 return (_size==0) ? true : false; 00175 } 00176 00177 template<class K, class I> 00178 inline void MNdictionary<K,I>::rotation (DI it) { 00179 // Rotation notwendig? 00180 while ( (it->father == NULL) ? false : (it->index < it->father->index) ) { 00181 DI father = it->father; 00182 // zuerst Großvater umbiegen 00183 DI opa = father->father; 00184 if (opa == NULL) { 00185 // Vater ist Wurzel 00186 _root = it; 00187 it->father = NULL; 00188 } else { 00189 if (opa->left == father) opa->left = it; else opa->right = it; 00190 it->father = opa; 00191 } 00192 father->father = it; 00193 // Rechtes oder linkes Kind des Vaters? 00194 if (father->left == it) { 00195 // Linkes Kind! 00196 DI temp = it->right; 00197 it->right = father; 00198 father->left = temp; 00199 if (temp != NULL) temp->father = father; 00200 } else { 00201 // Rechtes Kind! 00202 assert(father->right == it); 00203 DI temp = it->left; 00204 it->left = father; 00205 father->right = temp; 00206 if (temp != NULL) temp->father = father; 00207 } 00208 } 00209 } 00210 00211 template<class K, class I> 00212 inline void* MNdictionary<K,I>::insert (const K& k, const I& i) { 00213 if (_root == NULL) { 00214 // Falls Baum noch leer ist 00215 assert (empty()); 00216 _root = new _d_dic_item<K,I>(k,i); 00217 _size++; 00218 return (void*)_root; 00219 } else { 00220 // Baum ist nicht leer 00221 assert (_root != NULL); 00222 DI ins_pos = pos_finder(k); 00223 assert (ins_pos != NULL); 00224 DI it; 00225 switch (compare(k, ins_pos->key)) { 00226 case 0 : 00227 // Element existiert schon, muß ersetzt werden 00228 change_inf(ins_pos, i); 00229 it = ins_pos; 00230 break; 00231 case -1 : 00232 // Element existiert noch nicht, muß links erzeugt werden 00233 assert(ins_pos->left == NULL); 00234 it = new _d_dic_item<K,I>(k,i); 00235 it->father = ins_pos; 00236 ins_pos->left = it; 00237 _size++; 00238 rotation(it); 00239 break; 00240 case 1 : 00241 // Element existiert noch nicht, muß rechts erzeugt werden 00242 assert(ins_pos->right == NULL); 00243 it = new _d_dic_item<K,I>(k,i); 00244 it->father = ins_pos; 00245 ins_pos->right = it; 00246 _size++; 00247 rotation(it); 00248 break; 00249 default : assert(false); break; 00250 } 00251 return (void*)it; 00252 } 00253 } 00254 00255 template<class K, class I> 00256 inline _d_dic_item<K,I>* MNdictionary<K,I>::pos_finder (const K& k) const { 00257 /* Findet die Position eines Elements 00258 Gibt entweder den Knoten mit key=k zurück oder den Knoten, 00259 dessen Nachfolger ein Knoten mit key=k werden muß. 00260 Die Funktion MNdictionary.lookup() gibt im Gegensatz zu dieser 00261 Funktion ein NULL zurück wenn kein Element mit dem Wert k 00262 vorhanden ist.*/ 00263 assert (_root != NULL); 00264 DI next = _root; 00265 DI last; 00266 do { 00267 last = next; 00268 switch (compare(k, next->key)) { 00269 case -1 : next = next->left; break; 00270 case 1 : next = next->right; break; 00271 case 0 : next = NULL; break; 00272 default : assert(false); break; 00273 } 00274 } while (next != NULL); 00275 assert (last != NULL); 00276 return last; 00277 } 00278 00279 template<class K, class I> 00280 inline void* MNdictionary<K,I>::next_item (const void* it) const { 00281 if (it==NULL) return NULL; 00282 if (((DI)it)->right != NULL) { 00283 //kleinstes Element des Rechten Unterbaumes suchen 00284 return first_item( (void*) ((DI)it)->right ); 00285 } else { 00286 //nächstes Element ist also weiter oben im Baum zu suchen 00287 DI father = ((DI)it)->father; 00288 DI last = ((DI)it); 00289 while (father != NULL) { 00290 if (father->left == last) { 00291 //Ich komme aus dem linken Unterbaum 00292 //also ist der Vater das nächst größere Element 00293 return father; 00294 } else { 00295 //Ich komme aus dem rechten Unterbaum, muß also weiter oben suchen 00296 last = father; 00297 father = father->father; 00298 } 00299 } 00300 return NULL; //alle Elemente durch 00301 } 00302 } 00303 00304 template<class K, class I> 00305 inline void MNdictionary<K,I>::del_item (const void* it) { 00306 assert(it != NULL); //Darf nur auf existierende Elemente angewandt werden 00307 DI left = ((DI)it)->left; 00308 DI right = ((DI)it)->right; 00309 DI* app_pos; 00310 DI dad; 00311 if ((DI)it == _root) { 00312 // Löschen der Wurzel 00313 if ((left == NULL) & (right == NULL)) { 00314 _root = NULL; 00315 app_pos = NULL; //komplett leer 00316 } else { 00317 /* Hier wird überprüft ob einder der Söhne der Wurzel nicht vorhanden ist. 00318 Sind beide vorhanden wird überprüft welcher den Vorrang bekommt. */ 00319 if ( (left==NULL) ? false : ((right==NULL) ? true : (left->index < right->index)) ) { 00320 assert (left!=NULL); //Linker Sohn sollte vorhanden sein 00321 // Der linke Sohn wird neue Wurzel 00322 _root = left; 00323 // Linken Sohn als Wurzel kennzeichnen 00324 left->father = NULL; 00325 // Rechten Sohn der neuen Wurzel abtrennen 00326 app_pos = &(left->right); 00327 dad = left; 00328 left = left->right; 00329 } else { 00330 assert (right!=NULL); //Rechter Sohn sollte vorhanden sein 00331 _root = right; 00332 right->father = NULL; 00333 app_pos = &(right->left); 00334 dad = right; 00335 right = right->left; 00336 } 00337 } 00338 } else { 00339 // Löschen eines inneren Elementes 00340 dad = ((DI)it)->father; 00341 assert (dad != NULL); //Das nächste Element ist auf keinen Fall die Wurzel 00342 // War gelöschtes Element linker oder rechter Sohn seines Vaters 00343 app_pos = (dad->left == (DI)it) ? &(dad->left) : &(dad->right); 00344 } 00345 if (app_pos != NULL) { 00346 bool l_exists = (left != NULL); 00347 bool r_exists = (right != NULL); 00348 while ( l_exists & r_exists ) { 00349 if (left->index < right->index) { 00350 *app_pos = left; 00351 app_pos = &(left->right); 00352 left->father = dad; 00353 dad = left; 00354 left = left->right; 00355 l_exists = (left != NULL); 00356 } else { 00357 *app_pos = right; 00358 app_pos = &(right->left); 00359 right->father = dad; 00360 dad = right; 00361 right = right->left; 00362 r_exists = (right != NULL); 00363 } 00364 } 00365 if (l_exists) { 00366 *app_pos = left; 00367 left->father = dad; 00368 } else if (r_exists) { 00369 *app_pos = right; 00370 right->father = dad; 00371 } else *app_pos = NULL; 00372 } 00373 _size--; 00374 delete (DI)it; 00375 } 00376 00377 template<class K, class I> 00378 inline void MNdictionary<K,I>::clear_helper (DI it) { 00379 if (it->l() != NULL) 00380 { 00381 DI l = (DI)(it->l()); 00382 clear_helper( l ); 00383 } 00384 if (it->r() != NULL) 00385 { 00386 DI r = (DI)(it->r()); 00387 clear_helper( r ); 00388 } 00389 delete it; 00390 _size--; 00391 } 00392 00394 00395 /**********************************************************************/ 00396 /* StringDictionary */ 00397 /**********************************************************************/ 00398 00399 template <class I> class StringDictionary 00400 : public MNdictionary<MNString, I> 00401 { 00402 public: 00403 virtual int compare (const MNString& x, const MNString& y) const 00404 { 00405 int r = ::compare(x,y); 00406 if ( r<0 ) return -1; 00407 if ( r>0 ) return 1; 00408 return 0; 00409 } 00410 }; 00411 00412 #endif /* _MNDICTIONARY_H */ 00413

Generated on Sun Mar 6 13:35:49 2005 for Komssys by doxygen 1.3.8