Changeset 3555 for trunk/kStuff/include/k/kAVLTmpl/kAVLBase.h
- Timestamp:
- Aug 26, 2007, 12:43:27 PM (18 years ago)
- File:
-
- 1 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
Note:
See TracChangeset
for help on using the changeset viewer.