Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Related Pages

treeagenda.c

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 Author: Ingo Schroeder 00022 Birth: 22/7/99 00023 00024 $Id: treeagenda.c,v 1.4 2004/02/25 14:36:42 micha Exp $ 00025 */ 00026 00027 /* ---------------------------------------------------------------------- 00028 * @defgroup TreeAgenda TreeAgenda 00029 * 00030 * implemention of an agenda interface using an unbalanced binary search tree. 00031 * 00032 * This module exports an agenda as used in the CDG netsearch module. 00033 * The agenda manages a set of elements annoted with the ratings. 00034 * Elements can be inserted according to their rating, and the first element 00035 * can be retrieved.The agenda is not responsible for determining the rating 00036 * of an element;it can only deal with pairs(subsequently called items) of 00037 * elements and scores. 00038 * 00039 * \todo Actually the b-tree used here can be implemented in a more general 00040 * way to be more usefull. An agenda is just one way to use a b-treeish 00041 * storage organization. 00042 * @{ 00043 */ 00044 00045 /* -- INCLUDES -----------------------------------------------------------*/ 00046 00047 #include <stdio.h> 00048 #include <string.h> 00049 #include <blah.h> 00050 00051 /* -- MACROS -------------------------------------------------------------*/ 00052 #define TA_DEBUG 0 00053 00054 /* -- TYPE DEFINITIONS ---------------------------------------------------*/ 00055 00056 /* ------------------------------------------------------------------------- 00057 * this type represents an entry of an agenda. 00058 */ 00059 struct TANodeStruct { 00060 int parent; /**< index of parent node or -1 if root */ 00061 int better; /**< index of left child or -1 if non-existent */ 00062 int worse; /**< index of right child or -1 if non-existent */ 00063 double score; /**< score for this state */ 00064 Pointer state; /**< pointer to state */ 00065 }; 00066 00067 /* ------------------------------------------------------------------------- 00068 * quick, should be binary tree. 00069 */ 00070 struct TreeAgendaStruct { 00071 int size; /**< total number of used nodes */ 00072 int maxsize; /**< number of allocated nodes */ 00073 int maxSizeSoFar; /**< maximum number of used nodes so far */ 00074 Boolean verbose; /**< If set to true then truncation warnings take effect */ 00075 Boolean truncationWarning; /**< flag whether warning has been emitted */ 00076 int free; /**< index of first free node or -1 if non-existent */ 00077 int root; /**< index of root node or -1 if non-existent */ 00078 int best; /**< index of best node or -1 if non-existent */ 00079 int worst; /**< index of worst node or -1 if non-existent */ 00080 VoidFunction *freeState; /**< free function */ 00081 TANodeStruct *nodes; /**< array of maxsize nodes */ 00082 }; 00083 00084 /* ------------------------------------------------------------------------- 00085 * this structure instantiates the generic agenda iterator. 00086 */ 00087 00088 struct TreeAgendaIteratorStruct { 00089 TreeAgenda treeagenda; /**< points to the underlying TreeAgenda.*/ 00090 int nextNode; /**< an index to the next node to be returned.*/ 00091 }; 00092 00093 00094 /* -- FUNCTIONS ----------------------------------------------------------*/ 00095 00096 /* ------------------------------------------------------------------------- 00097 * prints a node. 00098 * 00099 * It is used by the taCheckNode(). 00100 * 00101 * @param a the TreeAgenda whose node has to be printed. 00102 * @param index the index of the node that has to be printed. 00103 */ 00104 void taPrintNode(TreeAgenda a, int index) 00105 { 00106 printf("[ %d ", index); 00107 00108 if (index >= 0) { 00109 printf("p %d ", a->nodes[index].parent); 00110 if (a->nodes[index].parent >= 0) { 00111 printf(" p's b %d p's w %d p's p %d ", 00112 a->nodes[a->nodes[index].parent].better, 00113 a->nodes[a->nodes[index].parent].worse, 00114 a->nodes[a->nodes[index].parent].parent); 00115 } 00116 printf("b %d ", a->nodes[index].better); 00117 if (a->nodes[index].better >= 0) { 00118 printf(" b's b %d b's w %d b's p %d ", 00119 a->nodes[a->nodes[index].better].better, 00120 a->nodes[a->nodes[index].better].worse, 00121 a->nodes[a->nodes[index].better].parent); 00122 } 00123 printf("w %d ", a->nodes[index].worse); 00124 if (a->nodes[index].worse >= 0) { 00125 printf(" w's b %d w's w %d w's p %d ", 00126 a->nodes[a->nodes[index].worse].better, 00127 a->nodes[a->nodes[index].worse].worse, 00128 a->nodes[a->nodes[index].worse].parent); 00129 } 00130 } 00131 printf("]"); 00132 } 00133 00134 /* ------------------------------------------------------------------------- 00135 * performs internal consistency checks on a TreeAgenda. 00136 * 00137 * This is only for debugging purposes. 00138 * 00139 * @param a the TreeAgenda that has to be checked. 00140 * @param index the index of the node in the treeagenda. 00141 * @param recursive is \a TRUE if repetition occurs and \a FALSE otherwise. 00142 * @param better is \a TRUE if better consistency and \a FALSE otherwise. 00143 * @returns the number of nodes that are checked. 00144 */ 00145 int taCheckNode(TreeAgenda a, int index, Boolean recursive, Boolean better) 00146 { 00147 int count; 00148 00149 if (index < 0) { 00150 return (0); 00151 } 00152 00153 if (a->best >= 0 && a->nodes[a->best].better >= 0) { 00154 printf("DEBUG: best inconsistency\n index "); 00155 taPrintNode(a, index); 00156 printf("\n best "); 00157 taPrintNode(a, a->best); 00158 printf("\n"); 00159 abort(); 00160 } 00161 00162 if (a->worst >= 0 && a->nodes[a->worst].worse >= 0) { 00163 printf("DEBUG: worst inconsistency\n index "); 00164 taPrintNode(a, index); 00165 printf("\n worst "); 00166 taPrintNode(a, a->worst); 00167 printf("\n"); 00168 abort(); 00169 } 00170 00171 if ((a->root != index && a->nodes[index].parent < 0) 00172 || (a->nodes[index].parent >= 0 && 00173 ((better && a->nodes[a->nodes[index].parent].better != index) 00174 || (!better && a->nodes[a->nodes[index].parent].worse != index)))) { 00175 printf("ERROR: %s inconsistency in node ", better && 00176 a->nodes[a->nodes[index].parent].better != 00177 index ? "left" : "right"); 00178 taPrintNode(a, index); 00179 printf("\n"); 00180 abort(); 00181 } 00182 00183 count = 1; 00184 if (recursive) { 00185 count += taCheckNode(a, a->nodes[index].better, recursive, TRUE); 00186 count += taCheckNode(a, a->nodes[index].worse, recursive, FALSE); 00187 } 00188 00189 return (count); 00190 } 00191 00192 /* ------------------------------------------------------------------------- 00193 * deletes a node. 00194 * 00195 * @param a the TreeAgenda in which a node has to be deleted. 00196 * @param index the index of the node that has to be deleted in TreeAgenda. 00197 * @param delete \a TRUE if the item itself is also deallocated and \a FALSE otherwise. 00198 */ 00199 int taDeleteNode(TreeAgenda a, int index, Boolean delete) 00200 { 00201 TANode node; 00202 int count; 00203 00204 if (index < 0) { 00205 return (0); 00206 } 00207 00208 node = &a->nodes[index]; 00209 00210 count = 1; 00211 count += taDeleteNode(a, node->better, delete); 00212 count += taDeleteNode(a, node->worse, delete); 00213 00214 if (delete) { 00215 (*a->freeState) (node->state); 00216 /* prepend node index to free node list */ 00217 node->parent = a->free; 00218 a->free = index; 00219 a->size--; 00220 if (index == a->root) { 00221 a->root = -1; 00222 printf("DEBUG: taDeleteNode, %d was root, resetting\n", index); 00223 } 00224 } 00225 00226 return (count); 00227 } 00228 00229 /* ------------------------------------------------------------------------- 00230 * creates a new agenda. 00231 * 00232 * @param maxsize determines the desired maximal size of an agenda. 00233 * @param f the function for deallocating the element. 00234 * @returns a pointer to the new structure that can hold upto \a maxsize entries. 00235 * 00236 * The agenda cannot determine whether it is safe to call this function on an 00237 * element or not.Passing the wrong function to a taNew() results undefined behaviour. 00238 */ 00239 TreeAgenda taNew(int maxsize, VoidFunction *f) 00240 { 00241 int i; 00242 TreeAgenda a; 00243 00244 if (maxsize < 1) { 00245 printf("WARNING: minimum size of agenda is 2, %d is too small\n", maxsize); 00246 /* 00247 * The fact that the minimum size is greater than 1 is explored at some points 00248 * in the code. 00249 */ 00250 maxsize = 2; 00251 } 00252 00253 a = (TreeAgenda) memMalloc(sizeof (TreeAgendaStruct)); 00254 a->size = 0; 00255 a->maxsize = maxsize; 00256 a->maxSizeSoFar = 0; 00257 a->verbose = FALSE; 00258 a->truncationWarning = FALSE; 00259 a->root = a->best = a->worst = -1; 00260 a->freeState = f; 00261 a->nodes = (TANodeStruct *) memMalloc(sizeof (TANodeStruct) * maxsize); 00262 memset(a->nodes, 0, sizeof (TANodeStruct) * maxsize); 00263 00264 for (i = 0; i < maxsize; i++) { 00265 a->nodes[i].parent = i - 1; 00266 } 00267 00268 a->free = maxsize - 1; 00269 00270 return (a); 00271 } 00272 00273 /* ---------------------------------------------------------------------- 00274 * gets verbosity flag. 00275 * \param a the TreeAgenda whose verbosity property is set 00276 * \returns the verbosity state 00277 */ 00278 Boolean taVerbosity(TreeAgenda a) 00279 { 00280 return a->verbose; 00281 } 00282 00283 /* ---------------------------------------------------------------------- 00284 * sets verbosity flag. 00285 * \param a the TreeAgenda whose verbosity property is set 00286 * \param b a Boolean which we set the verbosity to 00287 * \returns the old verbosity state 00288 */ 00289 Boolean taSetVerbosity(TreeAgenda a, Boolean b) 00290 { 00291 Boolean old = a->verbose; 00292 00293 a->verbose = b; 00294 return (old); 00295 } 00296 00297 00298 /* ------------------------------------------------------------------------- 00299 * retrieves size of the agenda. 00300 * 00301 * @param a the TreeAgenda for which the size has to be retrieved. 00302 * @returns the current number of entries in the TreeAgenda \a a. 00303 */ 00304 int taSize(TreeAgenda a) 00305 { 00306 return (a->size); 00307 } 00308 00309 /* ------------------------------------------------------------------------- 00310 * retrieves the size limit of the agenda. 00311 * 00312 * @param a the TreeAgenda for which the maximum size has to be determined. 00313 * @returns the max number of entries that can be held by the TreeAgenda a. 00314 */ 00315 int taMaxSize(TreeAgenda a) 00316 { 00317 return (a->maxsize); 00318 } 00319 00320 /* ------------------------------------------------------------------------- 00321 * retrieves the largest attained size of the agenda. 00322 * 00323 * @param a the TreeAgenda for which the largest size has to be retrieved. 00324 * @returns the maximum size occupied by the agenda \a a so far. 00325 */ 00326 int taMaxSizeSoFar(TreeAgenda a) 00327 { 00328 return (a->maxSizeSoFar); 00329 } 00330 00331 /* ------------------------------------------------------------------------- 00332 * checks if the specified TreeAgenda is empty. 00333 * 00334 * @param a the TreeAgenda for which emptiness has to be checked. 00335 * @returns \a TRUE if agenda \a a is empty and \a FALSE otherwise. 00336 */ 00337 Boolean taIsEmpty(TreeAgenda a) 00338 { 00339 return (a->size == 0); 00340 } 00341 00342 /* ------------------------------------------------------------------------- 00343 * checks for the truncation of the TreeAgenda \a a. 00344 * 00345 * @param a the TreeAgenda on which the function \a taIsTruncated is performed. 00346 * @returns \a TRUE if the agenda is already truncated and \a FALSE otherwise. 00347 */ 00348 Boolean taIsTruncated(TreeAgenda a) 00349 { 00350 return (a->truncationWarning); 00351 } 00352 00353 /* ------------------------------------------------------------------------- 00354 * reset the agenda truncation warning. 00355 * 00356 * @param a the TreeAgenda whose truncationWarning will be set to FALSE. 00357 * @returns the old value of the truncationWarning 00358 */ 00359 Boolean taResetTruncated(TreeAgenda a) 00360 { 00361 Boolean oldTruncationWarning = a->truncationWarning; 00362 a->truncationWarning = FALSE; 00363 return oldTruncationWarning; 00364 } 00365 00366 /* ------------------------------------------------------------------------- 00367 * inserts a new entry into the agenda. 00368 * 00369 * @param a the TreeAgenda into which a new element has to be inserted. 00370 * @param state the item that is inserted into the TreeAgenda \a a. 00371 * @param score the \a state is sorted into the list according to the \a score. 00372 * @returns \a FALSE if the agenda has been truncated and \a TRUE if we were able 00373 * to insert the item without any unpleasant side effects. This is going to 00374 * be reported only once. 00375 * 00376 * \n If the insertion leads to an overflow,then one of the elements from the 00377 * tree is deallocated.Note that the element to be removed may be the \a state itself. 00378 */ 00379 Boolean taInsert(TreeAgenda a, double score, Pointer state) 00380 { 00381 int i, parent, new, rightmost; 00382 TANode parentnode = NULL, newnode, rightmostnode; 00383 Boolean oldTruncationWarning = a->truncationWarning; 00384 00385 #if TA_DEBUG 00386 if (a->size != taCheckNode(a, a->root, TRUE, TRUE)) { 00387 abort(); 00388 } 00389 #endif 00390 00391 /* First, let's see whether the agenda is full */ 00392 if (a->size >= a->maxsize) { 00393 /* Yep, agenda is full. */ 00394 if (!a->truncationWarning) { 00395 if (a->verbose) { 00396 //printf("WARNING: truncating agenda, result may be incorrect\n"); 00397 } 00398 a->truncationWarning = TRUE; 00399 } 00400 #if TA_DEBUG 00401 /* Find worst node so far. */ 00402 for (rightmost = a->root; 00403 a->nodes[rightmost].worse >= 0; rightmost = a->nodes[rightmost].worse) { 00404 /* empty body */ 00405 } 00406 00407 if (rightmost != a->worst) { 00408 printf("DEBUG: rightmost inconsistency\n rightmost "); 00409 taPrintNode(a, rightmost); 00410 printf("\n worst "); 00411 taPrintNode(a, a->worst); 00412 printf("\n"); 00413 } 00414 #else 00415 rightmost = a->worst; 00416 #endif 00417 00418 /* rightmost is right most node and strictly >= 0 */ 00419 rightmostnode = &a->nodes[rightmost]; 00420 00421 /* Maybe the new state is really bad? */ 00422 if (score <= rightmostnode->score) { 00423 /* Yes, throw it away. */ 00424 (*a->freeState) (state); 00425 return (oldTruncationWarning != a->truncationWarning); 00426 } 00427 00428 /* At least one node is worse, delete that one. */ 00429 #if 0 00430 printf("WARNING: deleting old state %d with score %4.3f, new one is %4.3f\n", 00431 rightmost, rightmostnode->score, score); 00432 #endif 00433 (*a->freeState) (rightmostnode->state); 00434 if (rightmostnode->parent >= 0) { 00435 /* We have a parent, i. e. we aren't the root. */ 00436 a->nodes[rightmostnode->parent].worse = rightmostnode->better; 00437 if (rightmostnode->better >= 0) { 00438 a->nodes[rightmostnode->better].parent = rightmostnode->parent; 00439 for (a->worst = rightmostnode->better; 00440 a->worst >= 0 && a->nodes[a->worst].worse >= 0; 00441 a->worst = a->nodes[a->worst].worse) { 00442 /* empty body */ 00443 } 00444 } else { 00445 a->worst = rightmostnode->parent; 00446 } 00447 } else { 00448 /* We are the root */ 00449 if (rightmostnode->better >= 0) { 00450 a->nodes[rightmostnode->better].parent = -2; 00451 a->root = rightmostnode->better; 00452 for (a->worst = rightmostnode->better; 00453 a->worst >= 0 && a->nodes[a->worst].worse >= 0; 00454 a->worst = a->nodes[a->worst].worse) { 00455 /* empty body */ 00456 } 00457 } else { 00458 /* Can this happen? */ 00459 a->root = -1; 00460 a->worst = -1; 00461 } 00462 } 00463 00464 /* At this point we explore the fact that the agenda has a minimum 00465 * size of two. If the agenda is full it cannot be the case that 00466 * a->best == a->worst. That means we haven't deleted the best node 00467 * and we don't have to fix a->best. 00468 */ 00469 00470 /* a->free must be -1 at this point, because the agenda is full */ 00471 rightmostnode->parent = -3; 00472 a->free = rightmost; 00473 a->size--; 00474 } 00475 00476 /* Next, find parent of our new friend. */ 00477 i = a->root; 00478 parent = -4; 00479 while (i >= 0) { 00480 parent = i; 00481 parentnode = &a->nodes[i]; 00482 if (score >= parentnode->score) { 00483 i = parentnode->better; 00484 } else { 00485 i = parentnode->worse; 00486 } 00487 } 00488 00489 /* 00490 * parent is index to parent of new node 00491 * parent < 0 means agenda is empty, i. e. a->root == -1 00492 * parentnode is the corresponding node 00493 */ 00494 new = a->free; 00495 newnode = &a->nodes[new]; 00496 a->free = newnode->parent; 00497 a->size++; 00498 newnode->better = newnode->worse = -1; 00499 newnode->parent = parent; 00500 newnode->score = score; 00501 newnode->state = state; 00502 00503 if (a->root < 0) { 00504 /* Agenda seems to be empty, that's easy. */ 00505 a->root = a->best = a->worst = new; 00506 } else { 00507 if (score >= parentnode->score) { 00508 parentnode->better = new; 00509 if (a->best == parent) { 00510 a->best = new; 00511 } 00512 } else { 00513 parentnode->worse = new; 00514 if (a->worst == parent) { 00515 a->worst = new; 00516 } 00517 } 00518 } 00519 00520 if (a->maxSizeSoFar < a->size) { 00521 a->maxSizeSoFar = a->size; 00522 } 00523 00524 return (oldTruncationWarning != a->truncationWarning); 00525 } 00526 00527 /* ------------------------------------------------------------------------- 00528 * returns the best entry (= first) from the agenda. 00529 * 00530 * @param a the TreeAgenda from which the best item has to be retrieved. 00531 * @returns the best item in \a a (or NULL if a is empty).The item remains in the agenda. 00532 */ 00533 Pointer taBest(TreeAgenda a) 00534 { 00535 if (a->best < 0) { 00536 return (NULL); 00537 } else { 00538 return (a->nodes[a->best].state); 00539 } 00540 } 00541 00542 /* ------------------------------------------------------------------------- 00543 * removes and returns best entry (= first) from the agenda. 00544 * 00545 * @param a the TreeAgenda from which the best item has to be retrieved. 00546 * @returns the best item in \a a.The corresponding entry is removed and deallocated. 00547 * \n It must not be called on an empty agenda. 00548 */ 00549 Pointer taRemoveBest(TreeAgenda a) 00550 { 00551 int leftmost, parent, rightchild; 00552 00553 #if TA_DEBUG 00554 for (leftmost = a->root; 00555 leftmost >= 0 && a->nodes[leftmost].better >= 0; 00556 leftmost = a->nodes[leftmost].better) { 00557 /* empty body */ 00558 } 00559 if (leftmost != a->best) { 00560 printf("DEBUG: leftmost inconsistency\n leftmost "); 00561 taPrintNode(a, leftmost); 00562 printf("\n best "); 00563 taPrintNode(a, a->best); 00564 printf("\n size %d root %d\n", a->size, a->root); 00565 } 00566 #else 00567 leftmost = a->best; 00568 #endif 00569 00570 if (leftmost < 0) { 00571 printf("ERROR: taRemoveBest: agenda empty (size is %d)\n", a->size); 00572 return (NULL); 00573 } 00574 00575 /* leftmost is index to left node */ 00576 parent = a->nodes[leftmost].parent; 00577 rightchild = a->nodes[leftmost].worse; 00578 if (parent >= 0) { 00579 /* We have a parent, i. e. we aren't the root. */ 00580 a->nodes[parent].better = rightchild; 00581 if (rightchild >= 0) { 00582 a->nodes[rightchild].parent = parent; 00583 for (a->best = rightchild; 00584 a->best >= 0 && a->nodes[a->best].better >= 0; 00585 a->best = a->nodes[a->best].better) { 00586 /* empty body */ 00587 } 00588 } else { 00589 a->best = parent; 00590 } 00591 } else { 00592 /* We are the root */ 00593 if (rightchild >= 0) { 00594 a->nodes[rightchild].parent = -5; 00595 a->root = rightchild; 00596 for (a->best = a->root; 00597 a->best >= 0 && a->nodes[a->best].better >= 0; 00598 a->best = a->nodes[a->best].better) { 00599 /* empty body */ 00600 } 00601 } else { 00602 /* This is the only case where removing the best node 00603 * also means deleting the worst one. But this one 00604 * is trivial. 00605 */ 00606 a->root = a->best = a->worst = -1; 00607 } 00608 } 00609 00610 a->nodes[leftmost].parent = a->free; 00611 a->free = leftmost; 00612 a->size--; 00613 00614 return (a->nodes[leftmost].state); 00615 } 00616 00617 /* ------------------------------------------------------------------------- 00618 * deletes the specified agenda. 00619 * 00620 * The function deallocates all the items in \a a using *freeState(). 00621 * Then it deallocates all the entries and the agenda itself. 00622 * 00623 * @param a the ListAgenda that has to be deleted. 00624 */ 00625 void taDelete(TreeAgenda a) 00626 { 00627 int count; 00628 int oldSize; 00629 00630 oldSize = a->size; 00631 count = taDeleteNode(a, a->root, TRUE); 00632 if (count != oldSize) { 00633 printf("WARNING: taDelete, mismatch while deleting %d != %d\n", count, 00634 oldSize); 00635 } 00636 00637 memFree(a->nodes); 00638 memFree(a); 00639 } 00640 00641 /* ------------------------------------------------------------------------- 00642 * creates a new iterator object. 00643 * 00644 * This function creates a new iterator for TreeAgenda \a a. 00645 * 00646 * @param a the TreeAgenda for which a new iterator has to be created. 00647 * @returns a new TreeAgendaIterator that will return all items of \a a sorted by score. 00648 */ 00649 TreeAgendaIterator taIteratorNew(TreeAgenda a) 00650 { 00651 TreeAgendaIterator ai; 00652 00653 ai = (TreeAgendaIterator) memMalloc(sizeof (TreeAgendaIteratorStruct)); 00654 ai->treeagenda = a; 00655 ai->nextNode = a->best; 00656 return (ai); 00657 } 00658 00659 /* ------------------------------------------------------------------------- 00660 * returns the next item in iterator object. 00661 * 00662 * @param ai the iterator of the TreeAgenda \a a. 00663 * @returns the best item in the underlying agenda that was not already returned 00664 * by the iterator. 00665 */ 00666 Pointer taIteratorNextElement(TreeAgendaIterator ai) 00667 { 00668 Pointer state; 00669 int parent; 00670 00671 if (ai->nextNode < 0) { 00672 return (NULL); 00673 } 00674 state = ai->treeagenda->nodes[ai->nextNode].state; 00675 00676 if (ai->treeagenda->nodes[ai->nextNode].worse >= 0) { 00677 /* Find best node that's worse than the current node. */ 00678 for ( ai->nextNode = ai->treeagenda->nodes[ai->nextNode].worse; 00679 ai->treeagenda->nodes[ai->nextNode].better >= 0; 00680 ai->nextNode = ai->treeagenda->nodes[ai->nextNode].better ) { 00681 /* empty body */ 00682 } 00683 } else { 00684 parent = ai->treeagenda->nodes[ai->nextNode].parent; 00685 while (parent >= 0 && ai->nextNode == ai->treeagenda->nodes[parent].worse) { 00686 ai->nextNode = parent; 00687 parent = ai->treeagenda->nodes[ai->nextNode].parent; 00688 } 00689 ai->nextNode = parent; 00690 } 00691 00692 return (state); 00693 } 00694 00695 /* ------------------------------------------------------------------------- 00696 * deletes the iterator object. 00697 * 00698 * The function deallocates the tree element that was used by the iterator. 00699 * 00700 * @param ai the iterator object that has to be deleted. 00701 */ 00702 void taIteratorDelete(TreeAgendaIterator ai) 00703 { 00704 memFree(ai); 00705 } 00706 00707 /* ---------------------------------------------------------------------- */ 00708 /* -- ENDOFFILE --------------------------------------------------------- */ 00709 /** @} */

BLAH 0.95 (20 Oct 2004)