Changeset 3555
- Timestamp:
- Aug 26, 2007, 12:43:27 PM (18 years ago)
- Location:
- trunk/kStuff/include/k
- Files:
-
- 4 added
- 1 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kStuff/include/k/kAVLTmpl/kAVLBase.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLBase - basic routines for all AVL trees. 5 * 6 * Copyright (c) 2001-2002 knut st. osmundsen (bird@anduin.net) 7 * 8 * GPL 9 */ 10 11 #ifndef _kAVLBase_h_ 12 #define _kAVLBase_h_ 13 14 15 /** @design kAVL Template configuration. 16 * This is a template made to implemented multiple AVL trees. The difference 17 * between the implementations are related to the key used. 18 * 19 * #define KAVL_FN 20 * Use this to altern the names of the AVL functions. 21 * Must be defined. 22 * 23 * #define KAVL_EQUAL_ALLOWED 3 * kAVLTmpl - Templated AVL Trees, The Mandatory Base Code. 4 */ 5 6 /* 7 * Copyright (c) 2001-2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 26 27 28 /** @page pg_kAVLTmpl Template Configuration. 29 * 30 * This is a templated implementation of AVL trees in C. The template 31 * parameters relates to the kind of key used and how duplicates are 32 * treated. 33 * 34 * \#define KAVL_EQUAL_ALLOWED 24 35 * Define this to tell us that equal keys are allowed. 25 * Then Equal keys will be put a list pointed to by pList in the KAVLNODECORE.36 * Then Equal keys will be put in a list pointed to by KAVLNODECORE::pList. 26 37 * This is by default not defined. 27 38 * 28 * #define KAVL_CHECK_FOR_EQUAL_INSERT39 * \#define KAVL_CHECK_FOR_EQUAL_INSERT 29 40 * Define this to enable insert check for equal nodes. 30 41 * This is by default not defined. 31 42 * 32 * #define KAVL_MAX_STACK33 * Use this to specify the number of stack entries the stack we useswhen inserting34 * and removing nodes from the tree will need. I think the size should be about43 * \#define KAVL_MAX_STACK 44 * Use this to specify the max number of stack entries the stack will use when inserting 45 * and removing nodes from the tree. The size should be something like 35 46 * log2(<max nodes>) + 3 36 47 * Must be defined. 37 48 * 38 */ 49 * \#define KAVL_RANGE 50 * Define this to enable key ranges. 51 * 52 * \#define KAVL_OFFSET 53 * Define this to link the tree together using self relative offset 54 * instead of memory pointers, thus making the entire tree relocatable 55 * provided all the nodes - including the root node variable - are moved 56 * the exact same distance. 57 * 58 * \#define KAVLKEY 59 * Define this to the name of the AVL key type. 60 * 61 * \#define KAVL_STD_KEY_COMP 62 * Define this to use the standard key compare macros. If not set all the 63 * compare operations for KAVLKEY have to be defined: KAVL_G, KAVL_E, KAVL_NE, 64 * KAVL_R_IS_IDENTICAL, KAVL_R_IS_INTERSECTING and KAVL_R_IS_IN_RANGE. The latter 65 * three are only required when KAVL_RANGE is defined. 66 * 67 * \#define KAVLNODECORE 68 * Define this to the name (typedef) of the AVL core node structure. This 69 * structure must have a pLeft, pRight, Key and uchHeight member. 70 * If KAVL_RANGE is defined a KeyLast is also required. 71 * If KAVL_EQUAL_ALLOWED is defined a pList member is required. 72 * 73 * \#define KAVLTREEPTR 74 * Define this to the name (typedef) of the tree pointer type. This is 75 * required when KAVL_OFFSET is defined. When not defined it defaults 76 * to KAVLNODECORE *. 77 * 78 * \#define KAVL_FN 79 * Use this to alter the names of the AVL functions. 80 * Must be defined. 81 * 82 * \#define KAVL_TYPE(prefix, name) 83 * Use this to make external type names and unique. The prefix may be empty. 84 * Must be defined. 85 * 86 * \#define KAVL_INT(name) 87 * Use this to make internal type names and unique. The prefix may be empty. 88 * Must be defined. 89 * 90 * \#define KAVL_DECL(rettype) 91 * Function declaration macro that should be set according to the scope 92 * the instantiated template should have. For instance an inlined scope 93 * (private or public) should K_DECL_INLINE(rettype) here. 94 * 95 * typedef KAVL_TYPE(PFN,CALLBACK) 96 * kAVLDoWithAll requires KAVL_TYPE(PFN,CALLBACK) to be a function pointer 97 * to a callback suitable for the DoWithAll method. 98 * 99 * 100 * This version of the kAVL tree offers the option of inlining the entire 101 * implementation. This depends on the compiler doing a decent job in both 102 * making use of the inlined code and to eliminate const variables. 103 */ 104 105 106 /******************************************************************************* 107 * Internal Functions * 108 *******************************************************************************/ 109 #include <k/kDefs.h> 110 #include <k/kTypes.h> 111 #include <k/kHlpAssert.h> 112 39 113 40 114 /******************************************************************************* 41 115 * Defined Constants And Macros * 42 116 *******************************************************************************/ 43 #define AVL_HEIGHTOF(pNode) ((unsigned char)((pNode) != NULL ? pNode->uchHeight : 0)) 117 #define KAVL_HEIGHTOF(pNode) ((unsigned char)((pNode) != NULL ? (pNode)->uchHeight : 0)) 118 119 /** @def KAVL_GET_POINTER 120 * Reads a 'pointer' value. 121 * 122 * @returns The native pointer. 123 * @param pp Pointer to the pointer to read. 124 * @internal 125 */ 126 127 /** @def KAVL_GET_POINTER_NULL 128 * Reads a 'pointer' value which can be KAVL_NULL. 129 * 130 * @returns The native pointer. 131 * @returns NULL pointer if KAVL_NULL. 132 * @param pp Pointer to the pointer to read. 133 * @internal 134 */ 135 136 /** @def KAVL_SET_POINTER 137 * Writes a 'pointer' value. 138 * For offset-based schemes offset relative to pp is calculated and assigned to *pp. 139 * 140 * @returns stored pointer. 141 * @param pp Pointer to where to store the pointer. 142 * @param p Native pointer to assign to *pp. 143 * @internal 144 */ 145 146 /** @def KAVL_SET_POINTER_NULL 147 * Writes a 'pointer' value which can be KAVL_NULL. 148 * 149 * For offset-based schemes offset relative to pp is calculated and assigned to *pp, 150 * if p is not KAVL_NULL of course. 151 * 152 * @returns stored pointer. 153 * @param pp Pointer to where to store the pointer. 154 * @param pp2 Pointer to where to pointer to assign to pp. This can be KAVL_NULL 155 * @internal 156 */ 157 158 #ifndef KAVLTREEPTR 159 # define KAVLTREEPTR KAVLNODECORE * 160 #endif 161 162 #ifdef KAVL_OFFSET 163 # define KAVL_GET_POINTER(pp) ( (KAVLNODECORE *)((KIPTR)(pp) + *(pp)) ) 164 # define KAVL_GET_POINTER_NULL(pp) ( *(pp) != KAVL_NULL ? KAVL_GET_POINTER(pp) : NULL ) 165 # define KAVL_SET_POINTER(pp, p) ( (*(pp)) = ((KIPTR)(p) - (KIPTR)(pp)) ) 166 # define KAVL_SET_POINTER_NULL(pp, pp2) ( (*(pp)) = *(pp2) != KAVL_NULL ? (KIPTR)KAVL_GET_POINTER(pp2) - (KIPTR)(pp) : KAVL_NULL ) 167 #else 168 # define KAVL_GET_POINTER(pp) ( *(pp) ) 169 # define KAVL_GET_POINTER_NULL(pp) ( *(pp) ) 170 # define KAVL_SET_POINTER(pp, p) ( (*(pp)) = (p) ) 171 # define KAVL_SET_POINTER_NULL(pp, pp2) ( (*(pp)) = *(pp2) ) 172 #endif 173 174 175 /** @def KAVL_NULL 176 * The NULL 'pointer' equivalent. 177 */ 178 #ifdef KAVL_OFFSET 179 # define KAVL_NULL 0 180 #else 181 # define KAVL_NULL NULL 182 #endif 183 184 #ifdef KAVL_STD_KEY_COMP 185 # define KAVL_G(key1, key2) ( (key1) > (key2) ) 186 # define KAVL_E(key1, key2) ( (key1) == (key2) ) 187 # define KAVL_NE(key1, key2) ( (key1) != (key2) ) 188 # ifdef KAVL_RANGE 189 # define KAVL_R_IS_IDENTICAL(key1B, key2B, key1E, key2E) ( (key1B) == (key2B) && (key1E) == (key2E) ) 190 # define KAVL_R_IS_INTERSECTING(key1B, key2B, key1E, key2E) ( (key1B) <= (key2E) && (key1E) >= (key2B) ) 191 # define KAVL_R_IS_IN_RANGE(key1B, key1E, key2) KAVL_R_IS_INTERSECTING(key1B, key2, key1E, key2) 192 # endif 193 #endif 194 195 #ifndef KAVL_RANGE 196 # define KAVL_R_IS_INTERSECTING(key1B, key2B, key1E, key2E) KAVL_E(key1B, key2B) 197 # define KAVL_R_IS_IDENTICAL(key1B, key2B, key1E, key2E) KAVL_E(key1B, key2B) 198 #endif 199 44 200 45 201 … … 48 204 *******************************************************************************/ 49 205 /* 50 * A stack used to avoid recursive calls...51 */ 52 typedef struct _kAvlStack206 * Two stacks that's used to avoid recursive calls. 207 */ 208 typedef struct 53 209 { 54 210 unsigned cEntries; 55 PPKAVLNODECOREaEntries[KAVL_MAX_STACK];56 } KAVL STACK, *PKAVLSTACK;57 58 typedef struct _kAvlStack2211 KAVLTREEPTR *aEntries[KAVL_MAX_STACK]; 212 } KAVL_INT(STACK); 213 214 typedef struct 59 215 { 60 216 unsigned cEntries; 61 PKAVLNODECOREaEntries[KAVL_MAX_STACK];217 KAVLNODECORE *aEntries[KAVL_MAX_STACK]; 62 218 char achFlags[KAVL_MAX_STACK]; 63 } KAVLSTACK2, *PLAVLSTACK2; 64 65 66 /******************************************************************************* 67 * Internal Functions * 68 *******************************************************************************/ 69 KINLINE void KAVL_FN(Rebalance)(PKAVLSTACK pStack); 70 71 219 } KAVL_INT(STACK2); 220 221 222 /** 223 * Rewinds a stack of node pointer pointers, rebalancing the tree. 224 * 225 * @param pStack Pointer to stack to rewind. 226 * @sketch LOOP thru all stack entries 227 * BEGIN 228 * Get pointer to pointer to node (and pointer to node) from the stack. 229 * IF 2 higher left subtree than in right subtree THEN 230 * BEGIN 231 * IF higher (or equal) left-sub-subtree than right-sub-subtree THEN 232 * * n+2|n+3 233 * / \ / \ 234 * n+2 n ==> n+1 n+1|n+2 235 * / \ / \ 236 * n+1 n|n+1 n|n+1 n 237 * 238 * Or with keys: 239 * 240 * 4 2 241 * / \ / \ 242 * 2 5 ==> 1 4 243 * / \ / \ 244 * 1 3 3 5 245 * 246 * ELSE 247 * * n+2 248 * / \ / \ 249 * n+2 n n+1 n+1 250 * / \ ==> / \ / \ 251 * n n+1 n L R n 252 * / \ 253 * L R 254 * 255 * Or with keys: 256 * 6 4 257 * / \ / \ 258 * 2 7 ==> 2 6 259 * / \ / \ / \ 260 * 1 4 1 3 5 7 261 * / \ 262 * 3 5 263 * END 264 * ELSE IF 2 higher in right subtree than in left subtree THEN 265 * BEGIN 266 * Same as above but left <==> right. (invert the picture) 267 * ELSE 268 * IF correct height THEN break 269 * ELSE correct height. 270 * END 271 */ 272 K_DECL_INLINE(void) KAVL_FN(Rebalance)(KAVL_INT(STACK) *pStack) 273 { 274 while (pStack->cEntries > 0) 275 { 276 KAVLTREEPTR *ppNode = pStack->aEntries[--pStack->cEntries]; 277 KAVLNODECORE *pNode = KAVL_GET_POINTER(ppNode); 278 KAVLNODECORE *pLeftNode = KAVL_GET_POINTER_NULL(&pNode->pLeft); 279 unsigned char uchLeftHeight = KAVL_HEIGHTOF(pLeftNode); 280 KAVLNODECORE *pRightNode = KAVL_GET_POINTER_NULL(&pNode->pRight); 281 unsigned char uchRightHeight = KAVL_HEIGHTOF(pRightNode); 282 283 if (uchRightHeight + 1 < uchLeftHeight) 284 { 285 KAVLNODECORE *pLeftLeftNode = KAVL_GET_POINTER_NULL(&pLeftNode->pLeft); 286 KAVLNODECORE *pLeftRightNode = KAVL_GET_POINTER_NULL(&pLeftNode->pRight); 287 unsigned char uchLeftRightHeight = KAVL_HEIGHTOF(pLeftRightNode); 288 289 if (KAVL_HEIGHTOF(pLeftLeftNode) >= uchLeftRightHeight) 290 { 291 KAVL_SET_POINTER_NULL(&pNode->pLeft, &pLeftNode->pRight); 292 KAVL_SET_POINTER(&pLeftNode->pRight, pNode); 293 pLeftNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchLeftRightHeight))); 294 KAVL_SET_POINTER(ppNode, pLeftNode); 295 } 296 else 297 { 298 KAVL_SET_POINTER_NULL(&pLeftNode->pRight, &pLeftRightNode->pLeft); 299 KAVL_SET_POINTER_NULL(&pNode->pLeft, &pLeftRightNode->pRight); 300 KAVL_SET_POINTER(&pLeftRightNode->pLeft, pLeftNode); 301 KAVL_SET_POINTER(&pLeftRightNode->pRight, pNode); 302 pLeftNode->uchHeight = pNode->uchHeight = uchLeftRightHeight; 303 pLeftRightNode->uchHeight = uchLeftHeight; 304 KAVL_SET_POINTER(ppNode, pLeftRightNode); 305 } 306 } 307 else if (uchLeftHeight + 1 < uchRightHeight) 308 { 309 KAVLNODECORE *pRightLeftNode = KAVL_GET_POINTER_NULL(&pRightNode->pLeft); 310 unsigned char uchRightLeftHeight = KAVL_HEIGHTOF(pRightLeftNode); 311 KAVLNODECORE *pRightRightNode = KAVL_GET_POINTER_NULL(&pRightNode->pRight); 312 313 if (KAVL_HEIGHTOF(pRightRightNode) >= uchRightLeftHeight) 314 { 315 KAVL_SET_POINTER_NULL(&pNode->pRight, &pRightNode->pLeft); 316 KAVL_SET_POINTER(&pRightNode->pLeft, pNode); 317 pRightNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchRightLeftHeight))); 318 KAVL_SET_POINTER(ppNode, pRightNode); 319 } 320 else 321 { 322 KAVL_SET_POINTER_NULL(&pRightNode->pLeft, &pRightLeftNode->pRight); 323 KAVL_SET_POINTER_NULL(&pNode->pRight, &pRightLeftNode->pLeft); 324 KAVL_SET_POINTER(&pRightLeftNode->pRight, pRightNode); 325 KAVL_SET_POINTER(&pRightLeftNode->pLeft, pNode); 326 pRightNode->uchHeight = pNode->uchHeight = uchRightLeftHeight; 327 pRightLeftNode->uchHeight = uchRightHeight; 328 KAVL_SET_POINTER(ppNode, pRightLeftNode); 329 } 330 } 331 else 332 { 333 register unsigned char uchHeight = (unsigned char)(K_MAX(uchLeftHeight, uchRightHeight) + 1); 334 if (uchHeight == pNode->uchHeight) 335 break; 336 pNode->uchHeight = uchHeight; 337 } 338 } 339 340 } 72 341 73 342 … … 78 347 * @param ppTree Pointer to the AVL-tree root node pointer. 79 348 * @param pNode Pointer to the node which is to be added. 80 * @sketch Find the location of the node (using binary t hree algorithm.):349 * @sketch Find the location of the node (using binary tree algorithm.): 81 350 * LOOP until NULL leaf pointer 82 351 * BEGIN … … 89 358 * Fill in leaf node and insert it. 90 359 * Rebalance the tree. 91 * @status completely implemented. 92 * @author knut st. osmundsen 93 */ 94 KBOOL KLIBCALL KAVL_FN(Insert)(PPKAVLNODECORE ppTree, PKAVLNODECORE pNode) 360 */ 361 KAVL_DECL(KBOOL) KAVL_FN(Insert)(KAVLTREEPTR *ppTree, KAVLNODECORE *pNode) 95 362 { 96 KLOGENTRY2("KBOOL","PPKAVLNODECORE ppTree, PKAVLNODECORE pNode", ppTree, pNode); 97 KAVLSTACK AVLStack; 98 PPKAVLNODECORE ppCurNode = ppTree; 363 KAVL_INT(STACK) AVLStack; 364 KAVLTREEPTR *ppCurNode = ppTree; 99 365 register KAVLKEY Key = pNode->Key; 100 register PKAVLNODECORE pCurNode; 366 #ifdef KAVL_RANGE 367 register KAVLKEY KeyLast = pNode->KeyLast; 368 #endif 369 register KAVLNODECORE *pCurNode; 101 370 102 371 AVLStack.cEntries = 0; 103 372 104 while ((pCurNode = *ppCurNode) != NULL) 373 #ifdef KAVL_RANGE 374 if (Key > KeyLast) 375 return false; 376 #else 377 K_NOREF(Key); 378 #endif 379 380 while (*ppCurNode != KAVL_NULL) 105 381 { 106 kASSERT(AVLStack.cEntries < KAVL_MAX_STACK); 382 pCurNode = KAVL_GET_POINTER(ppCurNode); 383 384 kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK); 107 385 AVLStack.aEntries[AVLStack.cEntries++] = ppCurNode; 108 #ifndef KAVL_EQUAL_ALLOWED 109 if (AVL_G(pCurNode->Key, Key)) 110 ppCurNode = &pCurNode->pLeft; 111 else 112 ppCurNode = &pCurNode->pRight; 113 #else 114 if (AVL_G(pCurNode->Key, Key)) 115 ppCurNode = &pCurNode->pLeft; 116 else if (AVL_L(pCurNode->Key, Key)) 117 ppCurNode = &pCurNode->pRight; 118 else 386 #ifdef KAVL_EQUAL_ALLOWED 387 if (KAVL_R_IS_IDENTICAL(pCurNode->Key, Key, pCurNode->KeyLast, KeyLast)) 119 388 { 120 389 /* 121 390 * If equal then we'll use a list of equal nodes. 122 391 */ 123 pNode->pLeft = pNode->pRight = NULL;392 pNode->pLeft = pNode->pRight = KAVL_NULL; 124 393 pNode->uchHeight = 0; 125 pNode->pList = pCurNode->pList; 126 pCurNode->pList = pNode; 127 KLOGEXIT(FALSE); 128 return TRUE; 394 KAVL_SET_POINTER_NULL(&pNode->pList, &pCurNode->pList); 395 KAVL_SET_POINTER(&pCurNode->pList, pNode); 396 return K_TRUE; 129 397 } 130 #endif 398 #endif 399 #ifdef KAVL_CHECK_FOR_EQUAL_INSERT 400 if (KAVL_R_IS_INTERSECTING(pCurNode->Key, Key, pCurNode->KeyLast, KeyLast)) 401 return K_FALSE; 402 #endif 403 if (KAVL_G(pCurNode->Key, Key)) 404 ppCurNode = &pCurNode->pLeft; 405 else 406 ppCurNode = &pCurNode->pRight; 131 407 } 132 408 133 #ifdef KAVL_CHECK_FOR_EQUAL_INSERT 134 /* 135 * Fail if equal insert was attempted. 136 */ 137 if (AVLStack.cEntries > 0 && AVL_E((*AVLStack.aEntries[AVLStack.cEntries-1])->Key, pNode->Key)) 138 { 139 KLOGEXIT(FALSE); 140 return FALSE; 141 } 142 #endif 143 144 #ifndef KAVL_EQUAL_ALLOWED 145 pNode->pLeft = pNode->pRight = NULL; 146 #else 147 pNode->pList = pNode->pLeft = pNode->pRight = NULL; 148 #endif 409 pNode->pLeft = pNode->pRight = KAVL_NULL; 410 #ifdef KAVL_EQUAL_ALLOWED 411 pNode->pList = KAVL_NULL; 412 #endif 149 413 pNode->uchHeight = 1; 150 *ppCurNode = pNode; 151 152 KAVL_FN(Rebalance)(SSToDS(&AVLStack)); 153 KLOGEXIT(TRUE); 154 return TRUE; 414 KAVL_SET_POINTER(ppCurNode, pNode); 415 416 KAVL_FN(Rebalance)(&AVLStack); 417 return K_TRUE; 155 418 } 156 419 … … 194 457 * END 195 458 * return pointer to the removed node (if found). 196 * @status completely implemented. 197 * @author knut st. osmundsen 198 */ 199 PKAVLNODECORE KLIBCALL KAVL_FN(Remove)(PPKAVLNODECORE ppTree, KAVLKEY Key) 459 */ 460 KAVL_DECL(KAVLNODECORE *) KAVL_FN(Remove)(KAVLTREEPTR *ppTree, KAVLKEY Key) 200 461 { 201 KLOGENTRY2("PKAVLNODECORE","PPKAVLNODECORE ppTree, KAVLKEY Key", ppTree, Key); 202 KAVLSTACK AVLStack; 203 PPKAVLNODECORE ppDeleteNode = ppTree; 204 register PKAVLNODECORE pDeleteNode; 462 KAVL_INT(STACK) AVLStack; 463 KAVLTREEPTR *ppDeleteNode = ppTree; 464 register KAVLNODECORE *pDeleteNode; 205 465 206 466 AVLStack.cEntries = 0; 207 467 208 while ((pDeleteNode = *ppDeleteNode) != NULL)468 for (;;) 209 469 { 210 kASSERT(AVLStack.cEntries < KAVL_MAX_STACK); 470 if (*ppDeleteNode == KAVL_NULL) 471 return NULL; 472 pDeleteNode = KAVL_GET_POINTER(ppDeleteNode); 473 474 kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK); 211 475 AVLStack.aEntries[AVLStack.cEntries++] = ppDeleteNode; 212 #ifndef AVL_CMP 213 if (AVL_E(pDeleteNode->Key, Key)) 476 if (KAVL_E(pDeleteNode->Key, Key)) 214 477 break; 215 478 216 if ( AVL_G(pDeleteNode->Key, Key))479 if (KAVL_G(pDeleteNode->Key, Key)) 217 480 ppDeleteNode = &pDeleteNode->pLeft; 218 481 else 219 482 ppDeleteNode = &pDeleteNode->pRight; 220 #else 483 } 484 485 if (pDeleteNode->pLeft != KAVL_NULL) 486 { 487 /* find the rightmost node in the left tree. */ 488 const unsigned iStackEntry = AVLStack.cEntries; 489 KAVLTREEPTR *ppLeftLeast = &pDeleteNode->pLeft; 490 register KAVLNODECORE *pLeftLeast = KAVL_GET_POINTER(ppLeftLeast); 491 492 while (pLeftLeast->pRight != KAVL_NULL) 221 493 { 222 int register iDiff; 223 if ((iDiff = AVL_CMP(pDeleteNode->Key, Key)) == 0) 224 break; 225 226 if (iDiff > 0) 227 ppDeleteNode = &pDeleteNode->pLeft; 228 else 229 ppDeleteNode = &pDeleteNode->pRight; 494 kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK); 495 AVLStack.aEntries[AVLStack.cEntries++] = ppLeftLeast; 496 ppLeftLeast = &pLeftLeast->pRight; 497 pLeftLeast = KAVL_GET_POINTER(ppLeftLeast); 230 498 } 231 #endif 499 500 /* link out pLeftLeast */ 501 KAVL_SET_POINTER_NULL(ppLeftLeast, &pLeftLeast->pLeft); 502 503 /* link it in place of the delete node. */ 504 KAVL_SET_POINTER_NULL(&pLeftLeast->pLeft, &pDeleteNode->pLeft); 505 KAVL_SET_POINTER_NULL(&pLeftLeast->pRight, &pDeleteNode->pRight); 506 pLeftLeast->uchHeight = pDeleteNode->uchHeight; 507 KAVL_SET_POINTER(ppDeleteNode, pLeftLeast); 508 AVLStack.aEntries[iStackEntry] = &pLeftLeast->pLeft; 232 509 } 233 234 if (pDeleteNode != NULL) 510 else 235 511 { 236 if (pDeleteNode->pLeft != NULL) 237 { 238 unsigned iStackEntry = AVLStack.cEntries; 239 PPKAVLNODECORE ppLeftLeast = &pDeleteNode->pLeft; 240 register PKAVLNODECORE pLeftLeast; 241 242 while ((pLeftLeast = *ppLeftLeast)->pRight != NULL) /* Left most node. */ 243 { 244 kASSERT(AVLStack.cEntries < KAVL_MAX_STACK); 245 AVLStack.aEntries[AVLStack.cEntries++] = ppLeftLeast; 246 ppLeftLeast = &pLeftLeast->pRight; 247 pLeftLeast = pLeftLeast->pRight; 248 } 249 250 /* link out pLeftLeast */ 251 *ppLeftLeast = pLeftLeast->pLeft; 252 253 /* link in place of the delete node. */ 254 pLeftLeast->pLeft = pDeleteNode->pLeft; 255 pLeftLeast->pRight = pDeleteNode->pRight; 256 pLeftLeast->uchHeight = pDeleteNode->uchHeight; 257 *ppDeleteNode = pLeftLeast; 258 AVLStack.aEntries[iStackEntry] = &pLeftLeast->pLeft; 259 } 260 else 261 { 262 *ppDeleteNode = pDeleteNode->pRight; 263 AVLStack.cEntries--; 264 } 265 266 KAVL_FN(Rebalance)(SSToDS(&AVLStack)); 512 KAVL_SET_POINTER_NULL(ppDeleteNode, &pDeleteNode->pRight); 513 AVLStack.cEntries--; 267 514 } 268 515 269 K LOGEXIT(pDeleteNode);516 KAVL_FN(Rebalance)(&AVLStack); 270 517 return pDeleteNode; 271 518 } 272 519 273 274 /**275 * Rewindes a stack of pointer to pointers to nodes, rebalancing the tree.276 * @param pStack Pointer to stack to rewind.277 * @sketch LOOP thru all stack entries278 * BEGIN279 * Get pointer to pointer to node (and pointer to node) from stack.280 * IF 2 higher left subtree than in right subtree THEN281 * BEGIN282 * IF higher (or equal) left-sub-subtree than right-sub-subtree THEN283 * * n+2|n+3284 * / \ / \285 * n+2 n ==> n+1 n+1|n+2286 * / \ / \287 * n+1 n|n+1 n|n+1 n288 *289 * Or with keys:290 *291 * 4 2292 * / \ / \293 * 2 5 ==> 1 4294 * / \ / \295 * 1 3 3 5296 *297 * ELSE298 * * n+2299 * / \ / \300 * n+2 n n+1 n+1301 * / \ ==> / \ / \302 * n n+1 n L R n303 * / \304 * L R305 *306 * Or with keys:307 * 6 4308 * / \ / \309 * 2 7 ==> 2 6310 * / \ / \ / \311 * 1 4 1 3 5 7312 * / \313 * 3 5314 * END315 * ELSE IF 2 higher in right subtree than in left subtree THEN316 * BEGIN317 * Same as above but left <==> right. (invert the picture)318 * ELSE319 * IF correct height THEN break320 * ELSE correct height.321 * END322 * @status323 * @author knut st. osmundsen324 * @remark325 */326 KINLINE void KAVL_FN(Rebalance)(PKAVLSTACK pStack)327 {328 KLOGENTRY1("void","PKAVLSTACK pStack", pStack);329 while (pStack->cEntries > 0)330 {331 PPKAVLNODECORE ppNode = pStack->aEntries[--pStack->cEntries];332 PKAVLNODECORE pNode = *ppNode;333 PKAVLNODECORE pLeftNode = pNode->pLeft;334 unsigned char uchLeftHeight = AVL_HEIGHTOF(pLeftNode);335 PKAVLNODECORE pRightNode = pNode->pRight;336 unsigned char uchRightHeight = AVL_HEIGHTOF(pRightNode);337 338 if (uchRightHeight + 1 < uchLeftHeight)339 {340 PKAVLNODECORE pLeftLeftNode = pLeftNode->pLeft;341 PKAVLNODECORE pLeftRightNode = pLeftNode->pRight;342 unsigned char uchLeftRightHeight = AVL_HEIGHTOF(pLeftRightNode);343 344 if (AVL_HEIGHTOF(pLeftLeftNode) >= uchLeftRightHeight)345 {346 pNode->pLeft = pLeftRightNode;347 pLeftNode->pRight = pNode;348 pLeftNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchLeftRightHeight)));349 *ppNode = pLeftNode;350 }351 else352 {353 pLeftNode->pRight = pLeftRightNode->pLeft;354 pNode->pLeft = pLeftRightNode->pRight;355 pLeftRightNode->pLeft = pLeftNode;356 pLeftRightNode->pRight = pNode;357 pLeftNode->uchHeight = pNode->uchHeight = uchLeftRightHeight;358 pLeftRightNode->uchHeight = uchLeftHeight;359 *ppNode = pLeftRightNode;360 }361 }362 else if (uchLeftHeight + 1 < uchRightHeight)363 {364 PKAVLNODECORE pRightLeftNode = pRightNode->pLeft;365 unsigned char uchRightLeftHeight = AVL_HEIGHTOF(pRightLeftNode);366 PKAVLNODECORE pRightRightNode = pRightNode->pRight;367 368 if (AVL_HEIGHTOF(pRightRightNode) >= uchRightLeftHeight)369 {370 pNode->pRight = pRightLeftNode;371 pRightNode->pLeft = pNode;372 pRightNode->uchHeight = (unsigned char)(1 + (pNode->uchHeight = (unsigned char)(1 + uchRightLeftHeight)));373 *ppNode = pRightNode;374 }375 else376 {377 pRightNode->pLeft = pRightLeftNode->pRight;378 pNode->pRight = pRightLeftNode->pLeft;379 pRightLeftNode->pRight = pRightNode;380 pRightLeftNode->pLeft = pNode;381 pRightNode->uchHeight = pNode->uchHeight = uchRightLeftHeight;382 pRightLeftNode->uchHeight = uchRightHeight;383 *ppNode = pRightLeftNode;384 }385 }386 else387 {388 register unsigned char uchHeight = (unsigned char)(KMAX(uchLeftHeight, uchRightHeight) + 1);389 if (uchHeight == pNode->uchHeight)390 break;391 pNode->uchHeight = uchHeight;392 }393 }394 395 KLOGEXITVOID();396 }397 398 399 400 #endif -
trunk/kStuff/include/k/kAVLTmpl/kAVLDoWithAll.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLDoWithAll - Do with all nodes routine for AVL trees. 5 * 6 * Copyright (c) 1999-2002 knut st. osmundsen (bird@anduin.net) 7 * 8 * GPL 3 * kAVLTmpl - Templated AVL Trees, The Callback Iterator. 9 4 */ 10 5 11 #ifndef _kAVLDoWithAll_h_ 12 #define _kAVLDoWithAll_h_ 6 /* 7 * Copyright (c) 1999-2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 13 26 14 27 15 28 /** 16 29 * Iterates tru all nodes in the given tree. 17 * @returns 0 on success. Return from callback on failiure. 18 * @param ppTree Pointer to the AVL-tree root node pointer. 19 * @param fFromLeft TRUE: Left to right. 20 * FALSE: Right to left. 30 * 31 * @returns 0 on success. Return from callback on failure. 32 * @param ppTree Pointer to the AVL-tree root node pointer. 33 * @param fFromLeft K_TRUE: Left to right. 34 * K_FALSE: Right to left. 21 35 * @param pfnCallBack Pointer to callback function. 22 * @param pvParam Userparameter passed on to the callback function. 23 * @status completely implemented. 24 * @author knut st. osmundsen 36 * @param pvUser User parameter passed on to the callback function. 25 37 */ 26 unsigned KLIBCALL KAVL_FN(DoWithAll)(PPKAVLNODECORE ppTree, int fFromLeft, PKAVLCALLBACK pfnCallBack, void * pvParam)38 KAVL_DECL(int) KAVL_FN(DoWithAll)(KAVLTREEPTR *ppTree, KBOOL fFromLeft, KAVL_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser) 27 39 { 28 KLOGENTRY4("unsigned","PPKAVLNODECORE ppTree, int fFromLeft, PKAVLCALLBACK pfnCallBack, void * pvParam", ppTree, fFromLeft, pfnCallBack, pvParam); 29 KAVLSTACK2 AVLStack; 30 PKAVLNODECORE pNode; 31 unsigned rc; 40 KAVL_INT(STACK2) AVLStack; 41 KAVLNODECORE *pNode; 42 unsigned rc; 32 43 33 if (*ppTree == NULL)44 if (*ppTree == KAVL_NULL) 34 45 return 0; 35 46 36 47 AVLStack.cEntries = 1; 37 48 AVLStack.achFlags[0] = 0; 38 AVLStack.aEntries[0] = *ppTree;49 AVLStack.aEntries[0] = KAVL_GET_POINTER(ppTree); 39 50 40 51 if (fFromLeft) … … 47 58 if (!AVLStack.achFlags[AVLStack.cEntries - 1]++) 48 59 { 49 if (pNode->pLeft != NULL)60 if (pNode->pLeft != KAVL_NULL) 50 61 { 51 62 AVLStack.achFlags[AVLStack.cEntries] = 0; /* 0 first, 1 last */ 52 AVLStack.aEntries[AVLStack.cEntries++] = pNode->pLeft;63 AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pLeft); 53 64 continue; 54 65 } … … 56 67 57 68 /* center */ 58 rc = pfnCallBack(pNode, pvParam); 59 if (rc != 0) 60 { 61 KLOGEXIT(rc); 69 rc = pfnCallBack(pNode, pvUser); 70 if (rc) 62 71 return rc; 63 }64 72 65 73 /* right */ 66 74 AVLStack.cEntries--; 67 if (pNode->pRight != NULL)75 if (pNode->pRight != KAVL_NULL) 68 76 { 69 77 AVLStack.achFlags[AVLStack.cEntries] = 0; 70 AVLStack.aEntries[AVLStack.cEntries++] = pNode->pRight;78 AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pRight); 71 79 } 72 80 } /* while */ … … 82 90 if (!AVLStack.achFlags[AVLStack.cEntries - 1]++) 83 91 { 84 if (pNode->pRight != NULL)92 if (pNode->pRight != KAVL_NULL) 85 93 { 86 94 AVLStack.achFlags[AVLStack.cEntries] = 0; /* 0 first, 1 last */ 87 AVLStack.aEntries[AVLStack.cEntries++] = pNode->pRight;95 AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pRight); 88 96 continue; 89 97 } … … 91 99 92 100 /* center */ 93 rc = pfnCallBack(pNode, pvParam); 94 if (rc != 0) 95 { 96 KLOGEXIT(rc); 101 rc = pfnCallBack(pNode, pvUser); 102 if (rc) 97 103 return rc; 98 }99 104 100 105 /* left */ 101 106 AVLStack.cEntries--; 102 if (pNode->pLeft != NULL)107 if (pNode->pLeft != KAVL_NULL) 103 108 { 104 109 AVLStack.achFlags[AVLStack.cEntries] = 0; 105 AVLStack.aEntries[AVLStack.cEntries++] = pNode->pLeft;110 AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pLeft); 106 111 } 107 112 } /* while */ 108 113 } 109 114 110 KLOGEXIT(0);111 115 return 0; 112 116 } 113 117 114 115 #endif116 -
trunk/kStuff/include/k/kAVLTmpl/kAVLEnum.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLEnum - Enumeration routine for AVL trees. 5 * 6 * Copyright (c) 1999-2002 knut st. osmundsen (bird@anduin.net) 7 * 8 * GPL 3 * kAVLTmpl - Templated AVL Trees, Node Enumeration. 9 4 */ 10 5 11 #ifndef _kAVLEnum_h_ 12 #define _kAVLEnum_h_ 13 14 15 /** 16 * Starts an enumeration of all nodes in the given AVL tree. 17 * @returns Pointer to the first node in the tree. 18 * @param ppTree Pointer to the AVL-tree root node pointer. 19 * @param pEnumData Pointer to enumeration control data. 20 * @param fFromLeft TRUE: Left to right. 21 * FALSE: Right to left. 22 * @status completely implemented. 23 * @author knut st. osmundsen 6 /* 7 * Copyright (c) 1999-2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 24 25 */ 25 PKAVLNODECORE KLIBCALL KAVL_FN(BeginEnumTree)(PPKAVLNODECORE ppTree, PKAVLENUMDATA pEnumData, int fFromLeft)26 {27 KLOGENTRY3("PKAVLNODECORE","PPKAVLNODECORE ppTree, PKAVLENUMDATA pEnumData, int fFromLeft", ppTree, pEnumData, fFromLeft);28 PKAVLNODECORE pNode;29 if (*ppTree != NULL)30 {31 pEnumData->fFromLeft = (char)fFromLeft;32 pEnumData->cEntries = 1;33 pEnumData->aEntries[0] = *ppTree;34 pEnumData->achFlags[0] = 0;35 }36 else37 pEnumData->cEntries = 0;38 39 pNode = KAVL_FN(GetNextNode)(pEnumData);40 KLOGEXIT(pNode);41 return pNode;42 }43 44 26 45 27 /** … … 50 32 * @author knut st. osmundsen 51 33 */ 52 PKAVLNODECORE KLIBCALL KAVL_FN(GetNextNode)(PKAVLENUMDATApEnumData)34 KAVL_DECL(KAVLNODECORE *) KAVL_FN(GetNextNode)(KAVL_TYPE(,ENUMDATA) *pEnumData) 53 35 { 54 KLOGENTRY1("PKAVLNODECORE","PKAVLENUMDATA pEnumData", pEnumData);55 PKAVLNODECORE pNode;56 57 36 if (pEnumData->fFromLeft) 58 37 { /* from left */ 59 38 while (pEnumData->cEntries > 0) 60 39 { 61 pNode = pEnumData->aEntries[pEnumData->cEntries - 1];40 KAVLNODECORE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1]; 62 41 63 42 /* left */ … … 65 44 { 66 45 pEnumData->achFlags[pEnumData->cEntries - 1]++; 67 if (pNode->pLeft != NULL)46 if (pNode->pLeft != KAVL_NULL) 68 47 { 69 48 pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 left, 1 center, 2 right */ 70 pEnumData->aEntries[pEnumData->cEntries++] = pNode->pLeft;49 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->pLeft); 71 50 continue; 72 51 } … … 77 56 { 78 57 pEnumData->achFlags[pEnumData->cEntries - 1]++; 79 KLOGEXIT(pNode);80 58 return pNode; 81 59 } … … 83 61 /* right */ 84 62 pEnumData->cEntries--; 85 if (pNode->pRight != NULL)63 if (pNode->pRight != KAVL_NULL) 86 64 { 87 65 pEnumData->achFlags[pEnumData->cEntries] = 0; 88 pEnumData->aEntries[pEnumData->cEntries++] = pNode->pRight;66 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->pRight); 89 67 } 90 68 } /* while */ … … 94 72 while (pEnumData->cEntries > 0) 95 73 { 96 pNode = pEnumData->aEntries[pEnumData->cEntries - 1]; 97 74 KAVLNODECORE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1]; 98 75 99 76 /* right */ … … 101 78 { 102 79 pEnumData->achFlags[pEnumData->cEntries - 1]++; 103 if (pNode->pRight != NULL)80 if (pNode->pRight != KAVL_NULL) 104 81 { 105 82 pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 right, 1 center, 2 left */ 106 pEnumData->aEntries[pEnumData->cEntries++] = pNode->pRight;83 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->pRight); 107 84 continue; 108 85 } … … 113 90 { 114 91 pEnumData->achFlags[pEnumData->cEntries - 1]++; 115 KLOGEXIT(pNode);116 92 return pNode; 117 93 } … … 119 95 /* left */ 120 96 pEnumData->cEntries--; 121 if (pNode->pLeft != NULL)97 if (pNode->pLeft != KAVL_NULL) 122 98 { 123 99 pEnumData->achFlags[pEnumData->cEntries] = 0; 124 pEnumData->aEntries[pEnumData->cEntries++] = pNode->pLeft;100 pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->pLeft); 125 101 } 126 102 } /* while */ 127 103 } 128 104 129 KLOGEXIT(NULL);130 105 return NULL; 131 106 } 132 107 133 108 134 #endif 109 /** 110 * Starts an enumeration of all nodes in the given AVL tree. 111 * 112 * @returns Pointer to the first node in the enumeration. 113 * @param ppTree Pointer to the AVL-tree root node pointer. 114 * @param pEnumData Pointer to enumeration control data. 115 * @param fFromLeft K_TRUE: Left to right. 116 * K_FALSE: Right to left. 117 */ 118 KAVL_DECL(KAVLNODECORE *) KAVL_FN(BeginEnumTree)(KAVLTREEPTR *ppTree, KAVL_TYPE(,ENUMDATA) *pEnumData, KBOOL fFromLeft) 119 { 120 if (*ppTree != KAVL_NULL) 121 { 122 pEnumData->fFromLeft = fFromLeft; 123 pEnumData->cEntries = 1; 124 pEnumData->aEntries[0] = KAVL_GET_POINTER(ppTree); 125 pEnumData->achFlags[0] = 0; 126 } 127 else 128 pEnumData->cEntries = 0; 135 129 130 return KAVL_FN(GetNextNode)(pEnumData); 131 } 132 -
trunk/kStuff/include/k/kAVLTmpl/kAVLGet.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLGet - get routine for AVL trees. 5 * 6 * Copyright (c) 1999-2002 knut st. osmundsen (bird@anduin.net) 7 * 8 * GPL 3 * kAVLTmpl - Templated AVL Trees, Get a Node. 9 4 */ 10 5 11 #ifndef _kAVLGet_h_ 12 #define _kAVLGet_h_ 6 /* 7 * Copyright (c) 1999-2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 13 26 14 27 15 28 /** 16 29 * Gets a node from the tree (does not remove it!) 30 * 17 31 * @returns Pointer to the node holding the given key. 18 32 * @param ppTree Pointer to the AVL-tree root node pointer. 19 33 * @param Key Key value of the node which is to be found. 20 * @sketch21 * @status completely implemented.22 * @author knut st. osmundsen23 34 */ 24 PKAVLNODECORE KLIBCALL KAVL_FN(Get)(PPKAVLNODECOREppTree, KAVLKEY Key)35 KAVL_DECL(KAVLNODECORE *) KAVL_FN(Get)(KAVLTREEPTR *ppTree, KAVLKEY Key) 25 36 { 26 K LOGENTRY2("PKAVLNODECORE","PPKAVLNODECORE ppTree, KAVLKEY Key", ppTree, Key);27 #ifndef AVL_CMP28 register PKAVLNODECORE pNode = *ppTree;37 KAVLNODECORE *pNode; 38 if (*ppTree == KAVL_NULL) 39 return NULL; 29 40 30 while (pNode != NULL && AVL_NE(pNode->Key, Key)) 41 pNode = KAVL_GET_POINTER(ppTree); 42 while (KAVL_NE(pNode->Key, Key)) 31 43 { 32 if (AVL_G(pNode->Key, Key)) 33 pNode = pNode->pLeft; 44 if (KAVL_G(pNode->Key, Key)) 45 { 46 if (pNode->pLeft == KAVL_NULL) 47 return NULL; 48 pNode = KAVL_GET_POINTER(&pNode->pLeft); 49 } 34 50 else 35 pNode = pNode->pRight; 51 { 52 if (pNode->pRight == KAVL_NULL) 53 return NULL; 54 pNode = KAVL_GET_POINTER(&pNode->pRight); 55 } 36 56 } 37 38 #else39 40 register int iDiff;41 register PKAVLNODECORE pNode = *ppTree;42 43 while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)44 {45 if (iDiff > 0)46 pNode = pNode->pLeft;47 else48 pNode = pNode->pRight;49 }50 51 #endif52 53 KLOGEXIT(pNode);54 57 return pNode; 55 58 } 56 59 57 58 #endif -
trunk/kStuff/include/k/kAVLTmpl/kAVLGetBestFit.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLGetBestFit - Get Best Fit routine for AVL trees. 5 * Intended specially on heaps. The tree should allow duplicate keys. 6 * 7 * Copyright (c) 1999-2002 knut st. osmundsen (bird@anduin.net) 8 * 9 * GPL 3 * kAVLTmpl - Templated AVL Trees, Get Best Fitting Node. 10 4 */ 11 5 12 #ifndef _kAVLGetBestFit_h_ 13 #define _kAVLGetBestFit_h_ 6 /* 7 * Copyright (c) 1999-2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 14 26 15 27 16 28 /** 17 29 * Finds the best fitting node in the tree for the given Key value. 18 * @returns Pointer to the best fitting node found. 19 * @param ppTree Pointer to Pointer to the tree root node. 20 * @param Key The Key of which is to be found a best fitting match for.. 21 * @param fAbove TRUE: Returned node is have the closest key to Key from above. 22 * FALSE: Returned node is have the closest key to Key from below. 23 * @status completely implemented. 24 * @sketch The best fitting node is always located in the searchpath above you. 25 * >= (above): The node where you last turned left. 26 * <= (below): the node where you last turned right. 27 * @author knut st. osmundsen 30 * 31 * @returns Pointer to the best fitting node found. 32 * @param ppTree Pointer to Pointer to the tree root node. 33 * @param Key The Key of which is to be found a best fitting match for.. 34 * @param fAbove K_TRUE: Returned node is have the closest key to Key from above. 35 * K_FALSE: Returned node is have the closest key to Key from below. 36 * @sketch The best fitting node is always located in the searchpath above you. 37 * >= (above): The node where you last turned left. 38 * <= (below): the node where you last turned right. 28 39 */ 29 PKAVLNODECORE KLIBCALL KAVL_FN(GetBestFit)(PPKAVLNODECOREppTree, KAVLKEY Key, KBOOL fAbove)40 KAVL_DECL(KAVLNODECORE *) KAVL_FN(GetBestFit)(KAVLTREEPTR *ppTree, KAVLKEY Key, KBOOL fAbove) 30 41 { 31 KLOGENTRY3("PKAVLNODECORE","PPKAVLNODECORE ppTree, KAVLKEY Key, KBOOL fAbove", ppTree, Key, fAbove); 32 #ifdef AVL_CMP 33 register int iDiff; 34 #endif 35 register PKAVLNODECORE pNode = *ppTree; 36 PKAVLNODECORE pNodeLast = NULL; 42 register KAVLNODECORE *pNode; 43 KAVLNODECORE *pNodeLast; 37 44 45 if (*ppTree == KAVL_NULL) 46 return NULL; 47 48 pNode = KAVL_GET_POINTER(ppTree); 49 pNodeLast = NULL; 38 50 if (fAbove) 39 51 { /* pNode->Key >= Key */ 40 #ifndef AVL_CMP 41 while (pNode != NULL && AVL_NE(pNode->Key, Key)) 42 #else 43 while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0) 44 #endif 52 while (KAVL_NE(pNode->Key, Key)) 45 53 { 46 #ifndef AVL_CMP 47 if (AVL_G(pNode->Key, Key)) 48 #else 49 if (iDiff > 0) 50 #endif 54 if (KAVL_G(pNode->Key, Key)) 51 55 { 56 if (pNode->pLeft == KAVL_NULL) 57 return pNode; 52 58 pNodeLast = pNode; 53 pNode = pNode->pLeft;59 pNode = KAVL_GET_POINTER(&pNode->pLeft); 54 60 } 55 61 else 56 pNode = pNode->pRight; 62 { 63 if (pNode->pRight == KAVL_NULL) 64 return pNodeLast; 65 pNode = KAVL_GET_POINTER(&pNode->pRight); 66 } 57 67 } 58 68 } 59 69 else 60 70 { /* pNode->Key <= Key */ 61 #ifndef AVL_CMP 62 while (pNode != NULL && AVL_NE(pNode->Key, Key)) 63 #else 64 while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0) 65 #endif 71 while (KAVL_NE(pNode->Key, Key)) 66 72 { 67 #ifndef AVL_CMP 68 if (AVL_L(pNode->Key, Key)) 69 #else 70 if (iDiff < 0) 71 #endif 73 if (KAVL_G(pNode->Key, Key)) 72 74 { 73 pNodeLast = pNode; 74 pNode = pNode->pRight; 75 if (pNode->pLeft == KAVL_NULL) 76 return pNodeLast; 77 pNode = KAVL_GET_POINTER(&pNode->pLeft); 75 78 } 76 79 else 77 pNode = pNode->pLeft; 80 { 81 if (pNode->pRight == KAVL_NULL) 82 return pNode; 83 pNodeLast = pNode; 84 pNode = KAVL_GET_POINTER(&pNode->pRight); 85 } 78 86 } 79 87 } 80 88 81 KLOGEXIT(pNode == NULL ? pNodeLast /* best fit */ : pNode /* perfect match */);82 return pNode == NULL ? pNodeLast /* best fit */ : pNode /* perfect match */;89 /* perfect match or nothing. */ 90 return pNode; 83 91 } 84 92 85 86 #endif -
trunk/kStuff/include/k/kAVLTmpl/kAVLGetWithParent.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLGetWithParent - get with parent routine for AVL trees. 5 * 6 * Copyright (c) 1999-2002 knut st. osmundsen (bird@anduin.net) 7 * 8 * GPL 3 * kAVLTmpl - Templated AVL Trees, Get Node With Parent. 9 4 */ 10 5 11 #ifndef _kAVLGetWithParent_h_ 12 #define _kAVLGetWithParent_h_ 6 /* 7 * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 13 26 14 27 15 28 /** 16 * Gets a node from the tree and its parent node (if any) (does not remove any nodes!) 29 * Gets a node from the tree and its parent node (if any). 30 * The tree remains unchanged. 31 * 17 32 * @returns Pointer to the node holding the given key. 18 33 * @param ppTree Pointer to the AVL-tree root node pointer. … … 20 35 * return. When no node is found, this will hold the last searched node. 21 36 * @param Key Key value of the node which is to be found. 22 * @sketch23 * @status completely implemented.24 * @author knut st. osmundsen25 37 */ 26 PKAVLNODECORE KLIBCALL KAVL_FN(GetWithParent)(PPKAVLNODECORE ppTree, PPKAVLNODECOREppParent, KAVLKEY Key)38 KAVL_DECL(KAVLNODECORE *) KAVL_FN(GetWithParent)(KAVLTREEPTR *ppTree, KAVLNODECORE **ppParent, KAVLKEY Key) 27 39 { 28 KLOGENTRY3("PKAVLNODECORE","PPKAVLNODECORE ppTree, PPKAVLNODECORE ppParent, KAVLKEY Key", ppTree, ppParent, Key);29 #ifndef AVL_CMP40 register KAVLNODECORE *pNode = KAVL_GET_POINTER_NULL(ppTree); 41 register KAVLNODECORE *pParent = NULL; 30 42 31 register PKAVLNODECORE pNode = *ppTree; 32 register PKAVLNODECORE pParent = NULL; 33 34 while (pNode != NULL && AVL_NE(pNode->Key, Key)) 43 while ( pNode != NULL 44 && KAVL_NE(pNode->Key, Key)) 35 45 { 36 46 pParent = pNode; 37 if ( AVL_G(pNode->Key, Key))38 pNode = pNode->pLeft;47 if (KAVL_G(pNode->Key, Key)) 48 pNode = KAVL_GET_POINTER_NULL(&pNode->pLeft); 39 49 else 40 pNode = pNode->pRight;50 pNode = KAVL_GET_POINTER_NULL(&pNode->pRight); 41 51 } 42 52 43 #else44 45 register PKAVLNODECORE pNode = *ppTree;46 register PKAVLNODECORE pParent = NULL;47 register int iDiff;48 49 while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)50 {51 pParent = pNode;52 if (iDiff > 0)53 pNode = pNode->pLeft;54 else55 pNode = pNode->pRight;56 }57 58 #endif59 60 53 *ppParent = pParent; 61 KLOGEXIT(pNode);62 54 return pNode; 63 55 } 64 56 65 66 #endif67 -
trunk/kStuff/include/k/kAVLTmpl/kAVLRemove2.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLRemove2 - Remove specific node (by pointer) from an AVL tree. 5 * 6 * Copyright (c) 2001-2002 knut st. osmundsen (bird@anduin.net) 7 * 8 * GPL 3 * kAVLTmpl - Templated AVL Trees, Remove A Specific Node. 9 4 */ 10 5 11 #ifndef _kAVLRemove2_h_ 12 #define _kAVLRemove2_h_ 6 /* 7 * Copyright (c) 1999-2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 13 26 14 27 15 28 /** 16 * Removes a node from the AVL-tree given by it's pointer. 17 * @returns Pointer to the node. 18 * @param ppTree Pointer to the AVL-tree root node pointer. 19 * @param Key Key value of the node which is to be removed. 20 * @sketch Find the node which is to be removed: 21 * LOOP until not found 22 * BEGIN 23 * Add node pointer pointer to the AVL-stack. 24 * IF the keys matches THEN break! 25 * IF remove key < node key THEN 26 * left 27 * ELSE 28 * right 29 * END 30 * IF found THEN 31 * BEGIN 32 * IF duplicate keys allowed AND this isn't pNode Then 33 * BEGIN 34 * Search list (pList) for the node. 35 * IF found THEN Link it out and return it. 36 * return NULL (if not found). 37 * END 38 * IF duplicate keys allowed AND this is pNode AND there is nodes in the list Then 39 * Replace pNode with the first node in the list. 40 * END 41 * IF left node not empty THEN 42 * BEGIN 43 * Find the right most node in the left tree while adding the pointer to the pointer to it's parent to the stack: 44 * Start at left node. 45 * LOOP until right node is empty 46 * BEGIN 47 * Add to stack. 48 * go right. 49 * END 50 * Link out the found node. 51 * Replace the node which is to be removed with the found node. 52 * Correct the stack entry for the pointer to the left tree. 53 * END 54 * ELSE 55 * BEGIN 56 * Move up right node. 57 * Remove last stack entry. 58 * END 59 * Balance tree using stack. 60 * END 61 * return pointer to the removed node (if found). 62 * @status completely implemented. 63 * @author knut st. osmundsen 29 * Removes the specified node from the tree. 30 * 31 * @returns Pointer to the removed node (NULL if not in the tree) 32 * @param ppTree Pointer to Pointer to the tree root node. 33 * @param Key The Key of which is to be found a best fitting match for.. 34 * 35 * @remark This implementation isn't the most efficient, but this short and 36 * easier to manage. 64 37 */ 65 PKAVLNODECORE KLIBCALL KAVL_FN(Remove2)(PPKAVLNODECORE ppTree, PKAVLNODECOREpNode)38 KAVL_DECL(KAVLNODECORE *) KAVL_FN(Remove2)(KAVLTREEPTR *ppTree, KAVLNODECORE *pNode) 66 39 { 67 KLOGENTRY2("PKAVLNODECORE","PPKAVLNODECORE ppTree, PKAVLNODECORE pNode", ppTree, pNode); 68 KAVLKEY Key = pNode->Key;69 KAVLSTACK AVLStack;70 PPKAVLNODECORE ppDeleteNode = ppTree;71 register PKAVLNODECORE pDeleteNode;72 73 AVLStack.cEntries = 0;74 75 while ((pDeleteNode = *ppDeleteNode) != NULL)40 #ifdef KAVL_EQUAL_ALLOWED 41 /* 42 * Find the right node by key and see if it's what we want. 43 */ 44 KAVLNODECORE *pParent; 45 KAVLNODECORE *pCurNode = KAVL_FN(GetWithParent)(ppTree, pNode->Key, &pParent); 46 if (!pCurNode) 47 return NULL; 48 if (pCurNode != pNode) 76 49 { 77 kASSERT(AVLStack.cEntries < KAVL_MAX_STACK); 78 AVLStack.aEntries[AVLStack.cEntries++] = ppDeleteNode; 79 #ifndef AVL_CMP 80 if (AVL_E(pDeleteNode->Key, Key)) 81 break; 82 83 if (AVL_G(pDeleteNode->Key, Key)) 84 ppDeleteNode = &pDeleteNode->pLeft; 85 else 86 ppDeleteNode = &pDeleteNode->pRight; 87 #else 50 /* 51 * It's not the one we want, but it could be in the duplicate list. 52 */ 53 while (pCurNode->pList != KAVL_NULL) 88 54 { 89 int register iDiff;90 if ((iDiff = AVL_CMP(pDeleteNode->Key, Key)) == 0)91 break;92 93 if (iDiff > 0)94 ppDeleteNode = &pDeleteNode->pLeft;95 else96 p pDeleteNode = &pDeleteNode->pRight;55 KAVLNODECORE *pNext = KAVL_GET_POINTER(&pCurNode->pList); 56 if (pNext == pNode) 57 { 58 KAVL_SET_POINTER_NULL(&pCurNode->pList, KAVL_GET_POINTER_NULL(&pNode->pList)); 59 pNode->pList = KAVL_NULL; 60 return pNode; 61 } 62 pCurNode = pNext; 97 63 } 98 #endif64 return NULL; 99 65 } 100 66 101 if (pDeleteNode != NULL) 67 /* 68 * Ok, it's the one we want alright. 69 * 70 * Simply remove it if it's the only one with they Key, 71 * if there are duplicates we'll have to unlink it and 72 * insert the first duplicate in our place. 73 */ 74 if (pNode->pList == KAVL_NODE) 75 KAVL_FN(Remove)(ppTree, pNode->Key); 76 else 102 77 { 103 #ifdef KAVL_EQUAL_ALLOWED 104 if (pDeleteNode != pNode) 78 KAVLNODECORE *pNewUs = KAVL_GET_POINTER(&pNode->pList); 79 80 pNewUs->uchHeight = pNode->uchHeight; 81 82 if (pNode->pLeft != KAVL_NULL) 83 KAVL_SET_POINTER(&pNewUs->pLeft, KAVL_GET_POINTER(&pNode->pLeft)) 84 else 85 pNewUs->pLeft = KAVL_NULL; 86 87 if (pNode->pRight != KAVL_NULL) 88 KAVL_SET_POINTER(&pNewUs->pRight, KAVL_GET_POINTER(&pNode->pRight)) 89 else 90 pNewUs->pRight = KAVL_NULL; 91 92 if (pParent) 105 93 { 106 while (pDeleteNode->pList != NULL) 107 { 108 if (pDeleteNode->pList == pNode) 109 { 110 pDeleteNode->pList = pNode->pList; 111 pNode->pList = NULL; //debug only? 112 KLOGEXIT(pNode); 113 return pNode; 114 } 115 pDeleteNode = pDeleteNode->pList; 116 } 117 KLOGEXIT(NULL); 118 return NULL; 119 } 120 121 if (pDeleteNode->pList != NULL) 122 { 123 pDeleteNode = pDeleteNode->pList; 124 pDeleteNode->pLeft = pNode->pLeft; 125 pDeleteNode->pRight = pNode->pRight; 126 pDeleteNode->uchHeight = pNode->uchHeight; 127 kASSERT(*ppDeleteNode == pNode); 128 *ppDeleteNode = pDeleteNode; 129 pNode->pList = pNode->pLeft = pNode->pRight = NULL; //debug only? 130 KLOGEXIT(pNode); 131 return pNode; 132 } 133 #endif 134 135 if (pDeleteNode->pLeft != NULL) 136 { 137 unsigned iStackEntry = AVLStack.cEntries; 138 PPKAVLNODECORE ppLeftLeast = &pDeleteNode->pLeft; 139 register PKAVLNODECORE pLeftLeast; 140 141 while ((pLeftLeast = *ppLeftLeast)->pRight != NULL) /* Left most node. */ 142 { 143 kASSERT(AVLStack.cEntries < KAVL_MAX_STACK); 144 AVLStack.aEntries[AVLStack.cEntries++] = ppLeftLeast; 145 ppLeftLeast = &pLeftLeast->pRight; 146 pLeftLeast = pLeftLeast->pRight; 147 } 148 149 /* link out pLeftLeast */ 150 *ppLeftLeast = pLeftLeast->pLeft; 151 152 /* link in place of the delete node. */ 153 pLeftLeast->pLeft = pDeleteNode->pLeft; 154 pLeftLeast->pRight = pDeleteNode->pRight; 155 pLeftLeast->uchHeight = pDeleteNode->uchHeight; 156 *ppDeleteNode = pLeftLeast; 157 AVLStack.aEntries[iStackEntry] = &pLeftLeast->pLeft; 94 if (KAVL_GET_POINTER_NULL(&pParent->pLeft) == pNode) 95 KAVL_SET_POINTER(&pParent->pLeft, pNewUs); 96 else 97 KAVL_SET_POINTER(&pParent->pRight, pNewUs); 158 98 } 159 99 else 160 { 161 *ppDeleteNode = pDeleteNode->pRight; 162 AVLStack.cEntries--; 163 } 100 KAVL_SET_POINTER(ppTree, pNewUs); 101 } 102 return pNode; 164 103 165 KAVL_FN(Rebalance)(SSToDS(&AVLStack)); 166 } 104 #else 105 /* 106 * Delete it, if we got the wrong one, reinsert it. 107 * 108 * This ASSUMS that the caller is NOT going to hand us a lot 109 * of wrong nodes but just uses this API for his convenience. 110 */ 111 KAVLNODECORE *pRemovedNode = KAVL_FN(Remove)(ppTree, pNode->Key); 112 if (pRemovedNode == pNode) 113 return pRemovedNode; 167 114 168 #ifndef KAVL_EQUAL_ALLOWED //debug only? 169 pNode->pLeft = pNode->pRight = NULL; //debug only? 170 #else //debug only? 171 pNode->pList = pNode->pLeft = pNode->pRight = NULL; //debug only? 172 #endif //debug only? 173 KLOGEXIT(pDeleteNode); 174 return pDeleteNode; 115 KAVL_FN(Insert)(ppTree, pRemovedNode); 116 return NULL; 117 #endif 175 118 } 176 119 177 #endif -
trunk/kStuff/include/k/kAVLTmpl/kAVLRemoveBestFit.h
r3553 r3555 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * kAVLRemoveBestFit - Remove Best Fit routine for AVL trees. 5 * Intended specially on heaps. The tree should allow duplicate keys. 6 * 7 * Copyright (c) 1999-2002 knut st. osmundsen (bird@anduin.net) 8 * 9 * GPL 3 * kAVLTmpl - Templated AVL Trees, Remove Best Fitting Node. 10 4 */ 11 5 12 #ifndef _kAVLRemoveBestFit_h_ 13 #define _kAVLRemoveBestFit_h_ 6 /* 7 * Copyright (c) 1999-2007 knut st. osmundsen <bird-src-spam@anduin.net> 8 * 9 * This file is part of kStuff. 10 * 11 * kStuff is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2.1 of the License, or (at your option) any later version. 15 * 16 * kStuff is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with kStuff; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 */ 14 26 15 27 16 28 /** 17 * Finds the best fitting node in the tree for the given Key value. 18 * And removes it. 19 * @returns Pointer to the best fitting node found. 20 * @param ppTree Pointer to Pointer to the tree root node. 21 * @param Key The Key of which is to be found a best fitting match for.. 22 * @param fAbove TRUE: Returned node is have the closest key to Key from above. 23 * FALSE: Returned node is have the closest key to Key from below. 24 * @status completely implemented. 25 * @sketch The best fitting node is always located in the searchpath above you. 26 * >= (above): The node where you last turned left. 27 * <= (below): the node where you last turned right. 28 * @author knut st. osmundsen 29 * @remark This implementation should be speeded up slightly! 29 * Finds the best fitting node in the tree for the given Key value and removes the node. 30 * 31 * @returns Pointer to the removed node. 32 * @param ppTree Pointer to Pointer to the tree root node. 33 * @param Key The Key of which is to be found a best fitting match for.. 34 * @param fAbove K_TRUE: Returned node is have the closest key to Key from above. 35 * K_FALSE: Returned node is have the closest key to Key from below. 36 * 37 * @remark This implementation uses GetBestFit and then Remove and might therefore 38 * not be the most optimal kind of implementation, but it reduces the complexity 39 * code size, and the likelyhood for bugs. 30 40 */ 31 PKAVLNODECORE KLIBCALL KAVL_FN(RemoveBestFit)(PPKAVLNODECOREppTree, KAVLKEY Key, KBOOL fAbove)41 KAVL_DECL(KAVLNODECORE *) KAVL_FN(RemoveBestFit)(KAVLTREEPTR *ppTree, KAVLKEY Key, KBOOL fAbove) 32 42 { 33 KLOGENTRY3("PKAVLNODECORE","PPKAVLNODECORE ppTree, KAVLKEY Key, KBOOL fAbove", ppTree, Key, fAbove); 34 #ifdef AVL_CMP 35 register int iDiff; 36 #endif 37 register PKAVLNODECORE pNode = *ppTree; 38 PKAVLNODECORE pNodeLast = NULL; 39 40 if (fAbove) 41 { /* pNode->Key >= Key */ 42 #ifndef AVL_CMP 43 while (pNode != NULL && AVL_NE(pNode->Key, Key)) 44 #else 45 while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0) 46 #endif 43 /* 44 * If we find anything we'll have to remove the node and return it. 45 * Now, if duplicate keys are allowed we'll remove a duplicate before 46 * removing the in-tree node as this is way cheaper. 47 */ 48 KAVLNODECORE *pNode = KAVL_FN(GetBestFit)(ppTree, Key, fAbove); 49 if (pNode != NULL) 50 { 51 #ifdef KAVL_EQUAL_ALLOWED 52 if (pNode->pList != KAVL_NULL) 47 53 { 48 #ifndef AVL_CMP 49 if (AVL_G(pNode->Key, Key)) 50 #else 51 if (iDiff > 0) 52 #endif 53 { 54 pNodeLast = pNode; 55 pNode = pNode->pLeft; 56 } 57 else 58 pNode = pNode->pRight; 54 KAVLANODECORE *pRet = KAVL_GET_POINTER(&pNode->pList); 55 KAVL_SET_POINTER_NULL(&pNode->pList, &pRet->pList); 56 return pRet; 59 57 } 58 #endif 59 pNode = KAVL_FN(Remove)(ppTree, pNode->Key); 60 60 } 61 else62 { /* pNode->Key <= Key */63 #ifndef AVL_CMP64 while (pNode != NULL && AVL_NE(pNode->Key, Key))65 #else66 while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)67 #endif68 {69 #ifndef AVL_CMP70 if (AVL_L(pNode->Key, Key))71 #else72 if (iDiff < 0)73 #endif74 {75 pNodeLast = pNode;76 pNode = pNode->pRight;77 }78 else79 pNode = pNode->pLeft;80 }81 }82 83 /*84 * If we found anything we'll have to remove the node and return it.85 * If duplicate keys are allowed we'll check for multiple nodes first86 * and return one of them before doing an expensive remove operation87 * of the node we found.88 */89 if (pNode == NULL)90 pNode = pNodeLast;91 if (pNode == NULL)92 {93 KLOGEXIT(NULL);94 return NULL;95 }96 #ifdef KAVL_EQUAL_ALLOWED97 if (pNode->pList)98 {99 pNodeLast = pNode->pList;100 pNode->pList = pNodeLast->pList;101 KLOGEXIT(pNodeLast);102 return pNodeLast;103 }104 #endif105 pNode = KAVL_FN(Remove)(ppTree, pNode->Key);106 KLOGEXIT(pNode);107 61 return pNode; 108 62 } 109 63 110 111 #endif
Note:
See TracChangeset
for help on using the changeset viewer.