00001 /* 00002 00003 The BLAH library, a container library 00004 Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 00020 Contact: blah@nats.informatik.uni-hamburg.de 00021 00022 $Id: listagenda.c,v 1.5 2004/03/23 14:21:58 micha Exp $ 00023 00024 Author: Ingo Schroeder 00025 Birth: 23-Apr-97 00026 00027 $Id: listagenda.c,v 1.5 2004/03/23 14:21:58 micha Exp $ 00028 */ 00029 00030 /* ---------------------------------------------------------------------- 00031 * @defgroup ListAgenda ListAgenda 00032 * 00033 * This module is an implementation of the agenda interface using a plain list 00034 * as its the storage medium. 00035 * 00036 * This is used by the module netsearch, 00037 * but has been superseded by the more efficienct module treeagenda. 00038 * @{ 00039 */ 00040 00041 /* -- INCLUDES ------------------------------------------------------- */ 00042 #include <stdio.h> 00043 #include <blah.h> 00044 00045 /* -- TYPE DEFINITIONS ------------------------------------------------*/ 00046 00047 /* ---------------------------------------------------------------------- 00048 * this type represents an entry of an agenda. 00049 * 00050 * Only elements of the same type should be inserted into the same agenda, 00051 * since there can be only one function (freestate())for deallocating 00052 * the elements. 00053 */ 00054 00055 struct ListAgendaEntryStruct { 00056 double score; /**< contains the rating of an agenda element. 00057 Large scores are sorted to appear before 00058 small scores. 00059 */ 00060 Pointer state; /**< holds a pointer to the actual element. 00061 Since its type is unknown, the agenda 00062 never uses this value except to return it. 00063 */ 00064 }; 00065 00066 /* ---------------------------------------------------------------------- 00067 * quick, should be binary tree. 00068 */ 00069 struct ListAgendaStruct { 00070 int maxsize; /**< Gives the maximal allowed size of the agenda. 00071 If more elements are inserted to it,the agenda 00072 will overflow,and the elements with the worst 00073 scores will be lost. 00074 */ 00075 Boolean verbose; /**< If set to true then truncation warnings take effect */ 00076 Boolean truncationWarning; /**< This is set after an overflow messsage is printed. 00077 It inhibits any further warning messages. 00078 */ 00079 int size; /**< gives the current size of the agenda. */ 00080 int maxSizeSoFar; /**< gives the maximal value that the size has reached 00081 so far. 00082 */ 00083 double worstScore; /**< holds the score of the last item of the agenda. 00084 This field helps us to quickly determine whether 00085 an insert operation will make the agenda overflow. 00086 */ 00087 VoidFunction *freeState; /**< used on an element when when it is lost through 00088 overflow or when the entire agenda is freed. 00089 */ 00090 List entries; /**< holds an item in an agenda. The agenda will allocate 00091 and deallocate its own items.The elements,however, 00092 will only be deallocated in special cases. 00093 */ 00094 }; 00095 00096 /**< Instantiates the generic agenda iterator. 00097 * 00098 * Since the ListAgenda is already sorted by score, 00099 * iterating does not require any further data structures. 00100 * The iterator only allocates one List cell, * which is 00101 * set to the point to whatever item is next.The list 00102 * entries are unaffected by this 00103 */ 00104 00105 /*--FUNCTIONS----------------------------------------------------------*/ 00106 00107 /* ---------------------------------------------------------------------- 00108 * creates a new ListAgenda. 00109 * 00110 * @param maxsize the maximum capacity of the new ListAgenda that has to be created. 00111 * @param f the function that used for deallocating an element. 00112 * @returns a pointer to a new ListAgenda that can hold upto \a maxsize entries. 00113 */ 00114 ListAgenda laNew( int maxsize, VoidFunction f ) 00115 { 00116 ListAgenda a = (ListAgenda)memMalloc( sizeof(ListAgendaStruct) ); 00117 a->maxsize = maxsize; 00118 a->verbose = FALSE; 00119 a->truncationWarning = FALSE; 00120 a->maxSizeSoFar = 0; 00121 a->size = 0; 00122 a->worstScore = 0.0; 00123 a->freeState = f; 00124 a->entries = NULL; 00125 return( a ); 00126 } 00127 00128 /* ---------------------------------------------------------------------- 00129 * sets verbosity flag. 00130 * \param a the ListAgenda whose verbosity property is set 00131 * \param b a Boolean which we set the verbosity to 00132 * \returns the old verbosity state 00133 */ 00134 Boolean laSetVerbosity(ListAgenda a, Boolean b) 00135 { 00136 Boolean old = a->verbose; 00137 00138 a->verbose = b; 00139 return (old); 00140 } 00141 00142 /* ---------------------------------------------------------------------- 00143 * gets verbosity flag. 00144 * \param a the ListAgenda whose verbosity property is set 00145 * \returns the verbosity state 00146 */ 00147 Boolean laVerbosity(ListAgenda a) 00148 { 00149 return a->verbose; 00150 } 00151 00152 /* ---------------------------------------------------------------------- 00153 * retrieves size of the agenda. 00154 * 00155 * @param a the ListAgenda for which the size has to be retrieved. 00156 * @returns the current number of entries in the ListAgenda \a a. 00157 */ 00158 int laSize(ListAgenda a) 00159 { 00160 return (a->size); 00161 } 00162 00163 /* ---------------------------------------------------------------------- 00164 * retrieves the size limit of the agenda. 00165 * 00166 * @param a the ListAgenda for which the maximum size has to be determined. 00167 * @returns the max number of entries that can be held by the ListAgenda a. 00168 */ 00169 int laMaxSize( ListAgenda a ) 00170 { 00171 return(a->maxsize); 00172 } 00173 00174 /* ---------------------------------------------------------------------- 00175 * retrieves the largest attained size of the agenda. 00176 * 00177 * @param a the ListAgenda for which the largest size has to be retrieved. 00178 * @returns the maximum size occupied by the agenda \a a so far. 00179 */ 00180 int laMaxSizeSoFar(ListAgenda a) 00181 { 00182 return (a->maxSizeSoFar); 00183 } 00184 00185 /* ---------------------------------------------------------------------- 00186 * checks if the specified ListAgenda is empty. 00187 * 00188 * @param a the ListAgenda for which emptiness has to be checked. 00189 * @returns \a TRUE if agenda \a a is empty and \a FALSE otherwise. 00190 */ 00191 Boolean laIsEmpty(ListAgenda a) 00192 { 00193 return (a->size == 0); 00194 } 00195 00196 /* ---------------------------------------------------------------------- 00197 * checks for the truncation of the ListAgenda \a a. 00198 * 00199 * @param a the ListAgenda on which the function \a laIsTruncated is performed. 00200 * @returns \a TRUE if the agenda is already truncated and \a FALSE otherwise. 00201 */ 00202 Boolean laIsTruncated( ListAgenda a ) 00203 { 00204 return( a->truncationWarning ); 00205 } 00206 00207 /* ------------------------------------------------------------------------- 00208 * reset the agenda truncation warning. 00209 * 00210 * @param a the ListAgenda whose truncationWarning will be set to FALSE. 00211 * @returns the old value of the truncationWarning 00212 */ 00213 Boolean laResetTruncated(ListAgenda a) 00214 { 00215 Boolean oldTruncationWarning = a->truncationWarning; 00216 a->truncationWarning = FALSE; 00217 return oldTruncationWarning; 00218 } 00219 00220 /* ---------------------------------------------------------------------- 00221 * inserts a new entry into the agenda. 00222 * 00223 * @param a the ListAgenda into which a new element has to be inserted. 00224 * @param score the \a state is sorted into the list according to the \a score. 00225 * @param state the item that is inserted into the ListAgenda \a a. 00226 * @returns \a FALSE if the agenda has been truncated and \a TRUE if we were able 00227 * to insert the item without any unpleasant side effects. This is going to 00228 * be reported only once. 00229 * 00230 * \n If the insertion leads to an overflow, then the worst item from the list is removed. 00231 * Note that the item to be removed may be the \a state itself. 00232 */ 00233 Boolean laInsert(ListAgenda a, double score, Pointer state) 00234 { 00235 ListAgendaEntry ae; 00236 List l, k; 00237 int pos; 00238 00239 /* new entry is worse than the worst entry in the agenda */ 00240 if ( a->size >= a->maxsize && a->worstScore > score ) { 00241 (*a->freeState)( state ); 00242 if ( !a->truncationWarning ) { 00243 if (a->verbose) { 00244 //printf("WARNING: truncating agenda, result may be incorrect\n"); 00245 } 00246 a->truncationWarning = TRUE; 00247 return FALSE; 00248 } 00249 return TRUE; 00250 } 00251 00252 /* definitely put it on the agenda */ 00253 ae = (ListAgendaEntry)memMalloc( sizeof(ListAgendaEntryStruct) ); 00254 ae->score = score; 00255 ae->state = state; 00256 00257 pos = 1; 00258 if ( a->entries == NULL || ((ListAgendaEntry)listElement(a->entries))->score <= score ) { 00259 a->entries = listPrependElement( a->entries, ae ); 00260 k = a->entries; 00261 } else { 00262 /* find position where to insert item */ 00263 l = a->entries; 00264 while ( listNext(l) != NULL && ((ListAgendaEntry)listElement(listNext(l)))->score > score ) { 00265 l = listNext(l); 00266 pos++; 00267 } 00268 /* l is last element that is better than ae */ 00269 k = listAppendElement(NULL, ae); 00270 listSetNext(k, listNext(l)); 00271 listSetNext(l, k); 00272 } 00273 00274 /* k is list item that holds ae, pos is position of k */ 00275 a->size++; 00276 a->worstScore = listNext(k) == NULL ? score : a->worstScore; 00277 00278 if ( a->size > a->maxsize ) { 00279 while ( pos < a->maxsize && listNext(k) != NULL ) { 00280 k = listNext(k); 00281 pos++; 00282 } 00283 /* delete everything from listNext(k) on */ 00284 for ( l = listNext(k); l != NULL; l = listNext(l) ) { 00285 00286 (*a->freeState)(((ListAgendaEntry)listElement(l))->state ); 00287 00288 memFree( (ListAgendaEntry)listElement(l) ); 00289 } 00290 listDelete( listNext(k) ); 00291 listSetNext(k, NULL); 00292 a->worstScore = ((ListAgendaEntry)listElement(k))->score; 00293 a->size = pos; 00294 if ( !a->truncationWarning ) { 00295 //printf("WARNING: truncating agenda, result may be incorrect\n"); 00296 a->truncationWarning = TRUE; 00297 a->maxSizeSoFar = max( a->maxSizeSoFar, a->size ); 00298 return FALSE; 00299 } 00300 } 00301 00302 a->maxSizeSoFar = max( a->maxSizeSoFar, a->size ); 00303 00304 return TRUE; 00305 } 00306 00307 /* ---------------------------------------------------------------------- 00308 * returns the best entry (= first) from the agenda. 00309 * 00310 * @param a the ListAgenda from which the best item has to be retrieved. 00311 * @returns the best item in \a a (or NULL if a is empty).The item remains in the agenda. 00312 */ 00313 Pointer laBest( ListAgenda a ) 00314 { 00315 if ( a->entries == NULL ) 00316 { 00317 return (NULL); 00318 } 00319 else 00320 { 00321 return (listElement(a->entries)); 00322 } 00323 } 00324 /* ---------------------------------------------------------------------- 00325 * removes and returns best entry (= first) from the agenda. 00326 * 00327 * @param a the ListAgenda from which the best item has to be retrieved. 00328 * @returns the best item in \a a.The corresponding entry is removed and deallocated. 00329 * \n It must not be called on an empty agenda. 00330 */ 00331 Pointer laRemoveBest( ListAgenda a ) 00332 { 00333 Pointer p; 00334 List l; 00335 ListAgendaEntry ae; 00336 00337 l = a->entries; 00338 a->entries = listNext(a->entries); 00339 ae = (ListAgendaEntry)(listElement(l)); 00340 p = ae->state; 00341 00342 memFree( ae ); 00343 memFree( l ); 00344 a->size--; 00345 00346 return( p ); 00347 } 00348 00349 /* ---------------------------------------------------------------------- 00350 * deletes the specified agenda. 00351 * 00352 * The function deallocates all the items in \a a using *freeState(). 00353 * Then it deallocates all the entries and the agenda itself. 00354 * 00355 * @param a the ListAgenda that has to be deleted. 00356 */ 00357 void laDelete( ListAgenda a ) 00358 { 00359 List l, k; 00360 00361 l = a->entries; 00362 while ( l != NULL ) { 00363 (*a->freeState)( ((ListAgendaEntry)listElement(l))->state ); 00364 memFree( listElement(l) ); 00365 k = l; 00366 l = listNext(l); 00367 memFree( k ); 00368 } 00369 memFree( a ); 00370 } 00371 00372 /* ---------------------------------------------------------------------- 00373 * creates a new iterator object. 00374 * 00375 * This is actually just a single new list cell that points to the first entry. 00376 * 00377 * @param a the ListAgenda for which a new iterator has to be created. 00378 * @returns a new ListAgendaIterator that will return all items of \a a sorted by score. 00379 */ 00380 ListAgendaIterator laIteratorNew(ListAgenda a) 00381 { 00382 if ( a->entries != NULL ) 00383 { 00384 /* This allocates exactly one list cell. */ 00385 return (listPrependElement( a->entries, listElement(a->entries) )); 00386 } 00387 else 00388 { 00389 return (NULL); 00390 } 00391 } 00392 /* ---------------------------------------------------------------------- 00393 * returns the next item in iterator object. 00394 * 00395 * @param ai the iterator of the ListAgenda \a a. 00396 * @returns the best item in the underlying agenda that was not already returned 00397 * by the iterator. 00398 */ 00399 Pointer laIteratorNextElement(ListAgendaIterator ai) 00400 { 00401 Pointer result; 00402 00403 if ( listNext(ai) == NULL ) 00404 { 00405 return (NULL); 00406 } 00407 00408 result = ((ListAgendaEntry)(listElement(ai)))->state; 00409 listSetElement(ai, listElement(listNext(ai))); 00410 listSetNext(ai, listNext(listNext(ai))); 00411 00412 return (result); 00413 } 00414 00415 /* ---------------------------------------------------------------------- 00416 * deletes the iterator object. 00417 * 00418 * The function deallocates the list cell that was used by the iterator. 00419 * 00420 * @param ai the iterator object that has to be deleted. 00421 */ 00422 void laIteratorDelete(ListAgendaIterator ai) 00423 { 00424 memFree( ai ); 00425 } 00426 00427 /* ------------------------------------------------------------------- */ 00428 /* -- ENDOFFILE ------------------------------------------------------ */ 00429 /** @} */ 00430