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

dictionary.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 MN_OS_DICTIONARY_H 00025 #define MN_OS_DICTIONARY_H 00026 00027 #include "dict_both.h" 00028 #include <assert.h> 00029 #include <stdlib.h> 00030 #include <time.h> 00031 00032 /* #define nil NULL */ 00033 00034 /**********************************************************************/ 00035 /* preprocessor-generated compare() functions for basic types. 00036 * Definition of external compare functions for dictionaries that accept 00037 * a parameter-free constructor 00038 */ 00039 00040 #undef DEFINE_COMPARE 00041 #define DEFINE_COMPARE(T) \ 00042 extern int compare (const T& x, const T& y); 00043 00044 DEFINE_COMPARE(int) 00045 DEFINE_COMPARE(unsigned int) 00046 DEFINE_COMPARE(long) 00047 DEFINE_COMPARE(unsigned long) 00048 #ifdef HAVE_KEYWORD_BOOL 00049 DEFINE_COMPARE(bool) 00050 #endif 00051 DEFINE_COMPARE(char) 00052 DEFINE_COMPARE(unsigned char) 00053 DEFINE_COMPARE(float) 00054 00055 /**********************************************************************/ 00062 template <class K, class I> class dictionary 00063 { 00064 // type definitions 00065 public: 00066 typedef void* item; 00067 00068 private: 00069 typedef _d_dic_item<K,I>* DI; 00070 00071 // member variables 00072 private: 00073 int _size; 00074 DI root; 00075 int (*cmp_ptr) (const K &, const K &); 00076 00077 // constructors and destructor 00078 public: 00079 dictionary (){ 00080 _size = 0; 00081 root = NULL; 00082 cmp_ptr = &compare; 00083 srand((unsigned int) time(NULL)); 00084 } 00085 00086 /* 00087 * does not work ? 00088 * dictionary ( int (*cmp)(const K &, const K &) ) { 00089 * _size = 0; 00090 * root = NULL; 00091 * cmp_ptr = cmp; 00092 * srand((unsigned int) time(NULL)); 00093 * } 00094 */ 00095 00096 ~dictionary(); 00097 00098 // member functions 00099 public: 00100 K key (const void* it) const; 00101 I inf (const void* it) const; 00102 I& operator[] (const void* it) const; 00103 void* insert (const K k, const I i); 00104 void* lookup (const K k) const; 00105 I access (const K k) const; 00106 void del (const K k); 00107 void del_item (const void* it); 00108 void change_inf (const void* it, const I i); 00109 void clear () { 00110 if (root != NULL) { 00111 clear_helper(root); 00112 } 00113 root = NULL; 00114 } 00115 int size () const; 00116 bool empty () const; 00117 void* first_item ( void* start = NULL ) const; 00118 void* last_item () const; 00119 void* next_item (const void* it) const; 00120 private: 00121 void clear_helper (DI it); 00122 DI pos_finder (const K k) const; 00123 void rotation (DI it); 00124 }; 00125 00128 00129 template<class K, class I> dictionary<K,I>::~dictionary () { 00130 clear(); 00131 } 00132 00133 template<class K, class I> 00134 inline void* dictionary<K,I>::first_item ( void* start ) const { 00135 DI lastit = NULL; 00136 DI it = (start == NULL) ? root : (DI)start; 00137 while (it != NULL) { 00138 lastit = it; 00139 it = it->left; 00140 } 00141 return (void*)lastit; 00142 } 00143 00144 template<class K, class I> 00145 inline void* dictionary<K,I>::last_item () const { 00146 DI lastit = NULL; 00147 DI it = root; 00148 while (it != NULL) { 00149 lastit = it; 00150 it = it->right; 00151 } 00152 return (void*)lastit; 00153 } 00154 00155 template<class K, class I> 00156 inline K dictionary<K,I>::key (const void* it) const { 00157 return ((DI)it)->key; 00158 } 00159 00160 template<class K, class I> 00161 inline I dictionary<K,I>::inf (const void* it) const { 00162 return ((DI)it)->inf; 00163 } 00164 00165 template<class K, class I> 00166 inline I& dictionary<K,I>::operator[] (const void* it) const { 00167 return (((DI)it)->inf); 00168 } 00169 00170 template<class K, class I> 00171 inline void* dictionary<K,I>::lookup (const K k) const { 00172 if (root == NULL) return NULL; 00173 else { 00174 DI it = pos_finder(k); 00175 return (cmp_ptr(it->key, k) == 0) ? (void*)it : NULL; 00176 } 00177 } 00178 00179 template<class K, class I> 00180 inline I dictionary<K,I>::access (const K k) const { 00181 return inf(lookup(k)); 00182 } 00183 00184 template<class K, class I> 00185 inline void dictionary<K,I>::del (const K k) { 00186 void* it = lookup(k); 00187 if (it != NULL) del_item(it); 00188 } 00189 00190 template<class K, class I> 00191 inline void dictionary<K,I>::change_inf (const void* it, const I i) { 00192 ((DI)it)->inf = i; 00193 } 00194 00195 template<class K, class I> 00196 inline int dictionary<K,I>::size () const { 00197 return _size; 00198 } 00199 00200 template<class K, class I> 00201 inline bool dictionary<K,I>::empty () const { 00202 return (_size==0) ? true : false; 00203 } 00204 00205 template<class K, class I> 00206 inline void dictionary<K,I>::rotation (DI it) { 00207 // Rotation notwendig? 00208 while ( (it->father == NULL) ? false : (it->index < it->father->index) ) { 00209 DI father = it->father; 00210 // zuerst Großvater umbiegen 00211 DI opa = father->father; 00212 if (opa == NULL) { 00213 // Vater ist Wurzel 00214 root = it; 00215 it->father = NULL; 00216 } else { 00217 if (opa->left == father) opa->left = it; else opa->right = it; 00218 it->father = opa; 00219 } 00220 father->father = it; 00221 // Rechtes oder linkes Kind des Vaters? 00222 if (father->left == it) { 00223 // Linkes Kind! 00224 DI temp = it->right; 00225 it->right = father; 00226 father->left = temp; 00227 if (temp != NULL) temp->father = father; 00228 } else { 00229 // Rechtes Kind! 00230 assert(father->right == it); 00231 DI temp = it->left; 00232 it->left = father; 00233 father->right = temp; 00234 if (temp != NULL) temp->father = father; 00235 } 00236 } 00237 } 00238 00239 template<class K, class I> 00240 inline void* dictionary<K,I>::insert (const K k, const I i) { 00241 if (root == NULL) { 00242 // Falls Baum noch leer ist 00243 assert (empty()); 00244 root = new _d_dic_item<K,I>(k,i); 00245 _size++; 00246 return (void*)root; 00247 } else { 00248 // Baum ist nicht leer 00249 assert (root != NULL); 00250 DI ins_pos = pos_finder(k); 00251 assert (ins_pos != NULL); 00252 DI it; 00253 switch (cmp_ptr(k, ins_pos->key)) { 00254 case 0 : 00255 // Element existiert schon, muß ersetzt werden 00256 change_inf(ins_pos, i); 00257 it = ins_pos; 00258 break; 00259 case -1 : 00260 // Element existiert noch nicht, muß links erzeugt werden 00261 assert(ins_pos->left == NULL); 00262 it = new _d_dic_item<K,I>(k,i); 00263 it->father = ins_pos; 00264 ins_pos->left = it; 00265 _size++; 00266 rotation(it); 00267 break; 00268 case 1 : 00269 // Element existiert noch nicht, muß rechts erzeugt werden 00270 assert(ins_pos->right == NULL); 00271 it = new _d_dic_item<K,I>(k,i); 00272 it->father = ins_pos; 00273 ins_pos->right = it; 00274 _size++; 00275 rotation(it); 00276 break; 00277 default : assert(false); break; 00278 } 00279 return (void*)it; 00280 } 00281 } 00282 00283 template<class K, class I> 00284 inline _d_dic_item<K,I>* dictionary<K,I>::pos_finder (const K k) const { 00285 /* Findet die Position eines Elements 00286 Gibt entweder den Knoten mit key=k zurück oder den Knoten, 00287 dessen Nachfolger ein Knoten mit key=k werden muß. 00288 Die Funktion dictionary.lookup() gibt im Gegensatz zu dieser 00289 Funktion ein NULL zurück wenn kein Element mit dem Wert k 00290 vorhanden ist.*/ 00291 assert (root != NULL); 00292 DI next = root; 00293 DI last; 00294 do { 00295 last = next; 00296 switch (cmp_ptr(k, next->key)) { 00297 case -1 : next = next->left; break; 00298 case 1 : next = next->right; break; 00299 case 0 : next = NULL; break; 00300 default : assert(false); break; 00301 } 00302 } while (next != NULL); 00303 assert (last != NULL); 00304 return last; 00305 } 00306 00307 template<class K, class I> 00308 inline void* dictionary<K,I>::next_item (const void* it) const { 00309 if (it==NULL) return NULL; 00310 if (((DI)it)->right != NULL) { 00311 //kleinstes Element des Rechten Unterbaumes suchen 00312 return first_item( (void*) ((DI)it)->right ); 00313 } else { 00314 //nächstes Element ist also weiter oben im Baum zu suchen 00315 DI father = ((DI)it)->father; 00316 DI last = ((DI)it); 00317 while (father != NULL) { 00318 if (father->left == last) { 00319 //Ich komme aus dem linken Unterbaum 00320 //also ist der Vater das nächst größere Element 00321 return father; 00322 } else { 00323 //Ich komme aus dem rechten Unterbaum, muß also weiter oben suchen 00324 last = father; 00325 father = father->father; 00326 } 00327 } 00328 return NULL; //alle Elemente durch 00329 } 00330 } 00331 00332 template<class K, class I> 00333 inline void dictionary<K,I>::del_item (const void* it) { 00334 assert(it != NULL); //Darf nur auf existierende Elemente angewandt werden 00335 DI left = ((DI)it)->left; 00336 DI right = ((DI)it)->right; 00337 DI* app_pos; 00338 DI dad; 00339 if ((DI)it == root) { 00340 // Löschen der Wurzel 00341 if ((left == NULL) & (right == NULL)) { 00342 root = NULL; 00343 app_pos = NULL; //komplett leer 00344 } else { 00345 /* Hier wird überprüft ob einer der Söhne der Wurzel nicht vorhanden ist. 00346 Sind beide vorhanden wird überprüft welcher den Vorrang bekommt. */ 00347 if ( (left==NULL) ? false : ((right==NULL) ? true : (left->index < right->index)) ) { 00348 assert (left!=NULL); //Linker Sohn sollte vorhanden sein 00349 // Der linke Sohn wird neue Wurzel 00350 root = left; 00351 // Linken Sohn als Wurzel kennzeichnen 00352 left->father = NULL; 00353 // Rechten Sohn der neuen Wurzel abtrennen 00354 app_pos = &(left->right); 00355 dad = left; 00356 left = left->right; 00357 } else { 00358 assert (right!=NULL); //Rechter Sohn sollte vorhanden sein 00359 root = right; 00360 right->father = NULL; 00361 app_pos = &(right->left); 00362 dad = right; 00363 right = right->left; 00364 } 00365 } 00366 } else { 00367 // Löschen eines inneren Elementes 00368 dad = ((DI)it)->father; 00369 assert (dad != NULL); //Das nächste Element ist auf keinen Fall die Wurzel 00370 // War gelöschtes Element linker oder rechter Sohn seines Vaters 00371 app_pos = (dad->left == (DI)it) ? &(dad->left) : &(dad->right); 00372 } 00373 if (app_pos != NULL) { 00374 bool l_exists = (left != NULL); 00375 bool r_exists = (right != NULL); 00376 while ( l_exists & r_exists ) { 00377 if (left->index < right->index) { 00378 *app_pos = left; 00379 app_pos = &(left->right); 00380 left->father = dad; 00381 dad = left; 00382 left = left->right; 00383 l_exists = (left != NULL); 00384 } else { 00385 *app_pos = right; 00386 app_pos = &(right->left); 00387 right->father = dad; 00388 dad = right; 00389 right = right->left; 00390 r_exists = (right != NULL); 00391 } 00392 } 00393 if (l_exists) { 00394 *app_pos = left; 00395 left->father = dad; 00396 } else if (r_exists) { 00397 *app_pos = right; 00398 right->father = dad; 00399 } else *app_pos = NULL; 00400 } 00401 _size--; 00402 delete (DI)it; 00403 } 00404 00405 template<class K, class I> 00406 inline void dictionary<K,I>::clear_helper (DI it) { 00407 if (it->l() != NULL) 00408 { 00409 DI l = (DI)(it->l()); 00410 clear_helper( l ); 00411 } 00412 if (it->r() != NULL) 00413 { 00414 DI r = (DI)(it->r()); 00415 clear_helper( r ); 00416 } 00417 delete it; 00418 _size--; 00419 } 00420 00422 00423 #endif /* MN_OS_DICTIONARY_H */ 00424

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