Changeset 3555


Ignore:
Timestamp:
Aug 26, 2007, 12:43:27 PM (18 years ago)
Author:
bird
Message:

Merging in kAvl enhancements, doing some config simplications and made them inlineable.

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  
    11/* $Id$ */
    22/** @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
    2435 *  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.
    2637 *  This is by default not defined.
    2738 *
    28  *  #define KAVL_CHECK_FOR_EQUAL_INSERT
     39 *  \#define KAVL_CHECK_FOR_EQUAL_INSERT
    2940 *  Define this to enable insert check for equal nodes.
    3041 *  This is by default not defined.
    3142 *
    32  *  #define KAVL_MAX_STACK
    33  *  Use this to specify the number of stack entries the stack we uses when inserting
    34  *  and removing nodes from the tree will need. I think the size should be about
     43 *  \#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
    3546 *      log2(<max nodes>) + 3
    3647 *  Must be defined.
    3748 *
    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
    39113
    40114/*******************************************************************************
    41115*   Defined Constants And Macros                                               *
    42116*******************************************************************************/
    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
    44200
    45201
     
    48204*******************************************************************************/
    49205/*
    50  * A stack used to avoid recursive calls...
    51  */
    52 typedef struct _kAvlStack
     206 * Two stacks that's used to avoid recursive calls.
     207 */
     208typedef struct
    53209{
    54210    unsigned        cEntries;
    55     PPKAVLNODECORE  aEntries[KAVL_MAX_STACK];
    56 } KAVLSTACK, *PKAVLSTACK;
    57 
    58 typedef struct _kAvlStack2
     211    KAVLTREEPTR    *aEntries[KAVL_MAX_STACK];
     212} KAVL_INT(STACK);
     213
     214typedef struct
    59215{
    60216    unsigned        cEntries;
    61     PKAVLNODECORE   aEntries[KAVL_MAX_STACK];
     217    KAVLNODECORE   *aEntries[KAVL_MAX_STACK];
    62218    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 */
     272K_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}
    72341
    73342
     
    78347 * @param     ppTree  Pointer to the AVL-tree root node pointer.
    79348 * @param     pNode   Pointer to the node which is to be added.
    80  * @sketch    Find the location of the node (using binary three algorithm.):
     349 * @sketch    Find the location of the node (using binary tree algorithm.):
    81350 *            LOOP until NULL leaf pointer
    82351 *            BEGIN
     
    89358 *            Fill in leaf node and insert it.
    90359 *            Rebalance the tree.
    91  * @status    completely implemented.
    92  * @author    knut st. osmundsen
    93  */
    94 KBOOL KLIBCALL KAVL_FN(Insert)(PPKAVLNODECORE ppTree, PKAVLNODECORE pNode)
     360 */
     361KAVL_DECL(KBOOL) KAVL_FN(Insert)(KAVLTREEPTR *ppTree, KAVLNODECORE *pNode)
    95362{
    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;
    99365    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;
    101370
    102371    AVLStack.cEntries = 0;
    103372
    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)
    105381    {
    106         kASSERT(AVLStack.cEntries < KAVL_MAX_STACK);
     382        pCurNode = KAVL_GET_POINTER(ppCurNode);
     383
     384        kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK);
    107385        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))
    119388        {
    120389            /*
    121390             * If equal then we'll use a list of equal nodes.
    122391             */
    123             pNode->pLeft = pNode->pRight = NULL;
     392            pNode->pLeft = pNode->pRight = KAVL_NULL;
    124393            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;
    129397        }
    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;
    131407    }
    132408
    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
    149413    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;
    155418}
    156419
     
    194457 *            END
    195458 *            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 */
     460KAVL_DECL(KAVLNODECORE *) KAVL_FN(Remove)(KAVLTREEPTR *ppTree, KAVLKEY Key)
    200461{
    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;
    205465
    206466    AVLStack.cEntries = 0;
    207467
    208     while ((pDeleteNode = *ppDeleteNode) != NULL)
     468    for (;;)
    209469    {
    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);
    211475        AVLStack.aEntries[AVLStack.cEntries++] = ppDeleteNode;
    212         #ifndef AVL_CMP
    213         if (AVL_E(pDeleteNode->Key, Key))
     476        if (KAVL_E(pDeleteNode->Key, Key))
    214477            break;
    215478
    216         if (AVL_G(pDeleteNode->Key, Key))
     479        if (KAVL_G(pDeleteNode->Key, Key))
    217480            ppDeleteNode = &pDeleteNode->pLeft;
    218481        else
    219482            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)
    221493        {
    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);
    230498        }
    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;
    232509    }
    233 
    234     if (pDeleteNode != NULL)
     510    else
    235511    {
    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--;
    267514    }
    268515
    269     KLOGEXIT(pDeleteNode);
     516    KAVL_FN(Rebalance)(&AVLStack);
    270517    return pDeleteNode;
    271518}
    272519
    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 entries
    278  *            BEGIN
    279  *                Get pointer to pointer to node (and pointer to node) from stack.
    280  *                IF 2 higher left subtree than in right subtree THEN
    281  *                BEGIN
    282  *                    IF higher (or equal) left-sub-subtree than right-sub-subtree THEN
    283  *                                *                       n+2|n+3
    284  *                              /   \                     /     \
    285  *                            n+2    n       ==>         n+1   n+1|n+2
    286  *                           /   \                             /     \
    287  *                         n+1 n|n+1                          n|n+1  n
    288  *
    289  *                         Or with keys:
    290  *
    291  *                               4                           2
    292  *                             /   \                       /   \
    293  *                            2     5        ==>          1     4
    294  *                           / \                               / \
    295  *                          1   3                             3   5
    296  *
    297  *                    ELSE
    298  *                                *                         n+2
    299  *                              /   \                      /   \
    300  *                            n+2    n                   n+1   n+1
    301  *                           /   \           ==>        /  \   /  \
    302  *                          n    n+1                    n  L   R   n
    303  *                               / \
    304  *                              L   R
    305  *
    306  *                         Or with keys:
    307  *                               6                           4
    308  *                             /   \                       /   \
    309  *                            2     7        ==>          2     6
    310  *                          /   \                       /  \  /  \
    311  *                          1    4                      1  3  5  7
    312  *                              / \
    313  *                             3   5
    314  *                END
    315  *                ELSE IF 2 higher in right subtree than in left subtree THEN
    316  *                BEGIN
    317  *                    Same as above but left <==> right. (invert the picture)
    318  *                ELSE
    319  *                    IF correct height THEN break
    320  *                    ELSE correct height.
    321  *            END
    322  * @status
    323  * @author    knut st. osmundsen
    324  * @remark
    325  */
    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             else
    352             {
    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             else
    376             {
    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         else
    387         {
    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  
    11/* $Id$ */
    22/** @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.
    94 */
    105
    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 */
    1326
    1427
    1528/**
    1629 * 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.
    2135 * @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.
    2537 */
    26 unsigned KLIBCALL KAVL_FN(DoWithAll)(PPKAVLNODECORE ppTree, int fFromLeft, PKAVLCALLBACK pfnCallBack, void * pvParam)
     38KAVL_DECL(int) KAVL_FN(DoWithAll)(KAVLTREEPTR *ppTree, KBOOL fFromLeft, KAVL_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser)
    2739{
    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;
    3243
    33     if (*ppTree == NULL)
     44    if (*ppTree == KAVL_NULL)
    3445        return 0;
    3546
    3647    AVLStack.cEntries = 1;
    3748    AVLStack.achFlags[0] = 0;
    38     AVLStack.aEntries[0] = *ppTree;
     49    AVLStack.aEntries[0] = KAVL_GET_POINTER(ppTree);
    3950
    4051    if (fFromLeft)
     
    4758            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
    4859            {
    49                 if (pNode->pLeft != NULL)
     60                if (pNode->pLeft != KAVL_NULL)
    5061                {
    5162                    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);
    5364                    continue;
    5465                }
     
    5667
    5768            /* center */
    58             rc = pfnCallBack(pNode, pvParam);
    59             if (rc != 0)
    60             {
    61                 KLOGEXIT(rc);
     69            rc = pfnCallBack(pNode, pvUser);
     70            if (rc)
    6271                return rc;
    63             }
    6472
    6573            /* right */
    6674            AVLStack.cEntries--;
    67             if (pNode->pRight != NULL)
     75            if (pNode->pRight != KAVL_NULL)
    6876            {
    6977                AVLStack.achFlags[AVLStack.cEntries] = 0;
    70                 AVLStack.aEntries[AVLStack.cEntries++] = pNode->pRight;
     78                AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pRight);
    7179            }
    7280        } /* while */
     
    8290            if (!AVLStack.achFlags[AVLStack.cEntries - 1]++)
    8391            {
    84                 if (pNode->pRight != NULL)
     92                if (pNode->pRight != KAVL_NULL)
    8593                {
    8694                    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);
    8896                    continue;
    8997                }
     
    9199
    92100            /* center */
    93             rc = pfnCallBack(pNode, pvParam);
    94             if (rc != 0)
    95             {
    96                 KLOGEXIT(rc);
     101            rc = pfnCallBack(pNode, pvUser);
     102            if (rc)
    97103                return rc;
    98             }
    99104
    100105            /* left */
    101106            AVLStack.cEntries--;
    102             if (pNode->pLeft != NULL)
     107            if (pNode->pLeft != KAVL_NULL)
    103108            {
    104109                AVLStack.achFlags[AVLStack.cEntries] = 0;
    105                 AVLStack.aEntries[AVLStack.cEntries++] = pNode->pLeft;
     110                AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->pLeft);
    106111            }
    107112        } /* while */
    108113    }
    109114
    110     KLOGEXIT(0);
    111115    return 0;
    112116}
    113117
    114 
    115 #endif
    116 
  • trunk/kStuff/include/k/kAVLTmpl/kAVLEnum.h

    r3553 r3555  
    11/* $Id$ */
    22/** @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.
    94 */
    105
    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 *
    2425 */
    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     else
    37         pEnumData->cEntries = 0;
    38 
    39     pNode = KAVL_FN(GetNextNode)(pEnumData);
    40     KLOGEXIT(pNode);
    41     return pNode;
    42 }
    43 
    4426
    4527/**
     
    5032 * @author    knut st. osmundsen
    5133 */
    52 PKAVLNODECORE KLIBCALL KAVL_FN(GetNextNode)(PKAVLENUMDATA pEnumData)
     34KAVL_DECL(KAVLNODECORE *) KAVL_FN(GetNextNode)(KAVL_TYPE(,ENUMDATA) *pEnumData)
    5335{
    54     KLOGENTRY1("PKAVLNODECORE","PKAVLENUMDATA pEnumData", pEnumData);
    55     PKAVLNODECORE    pNode;
    56 
    5736    if (pEnumData->fFromLeft)
    5837    {   /* from left */
    5938        while (pEnumData->cEntries > 0)
    6039        {
    61             pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
     40            KAVLNODECORE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
    6241
    6342            /* left */
     
    6544            {
    6645                pEnumData->achFlags[pEnumData->cEntries - 1]++;
    67                 if (pNode->pLeft != NULL)
     46                if (pNode->pLeft != KAVL_NULL)
    6847                {
    6948                    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);
    7150                    continue;
    7251                }
     
    7756            {
    7857                pEnumData->achFlags[pEnumData->cEntries - 1]++;
    79                 KLOGEXIT(pNode);
    8058                return pNode;
    8159            }
     
    8361            /* right */
    8462            pEnumData->cEntries--;
    85             if (pNode->pRight != NULL)
     63            if (pNode->pRight != KAVL_NULL)
    8664            {
    8765                pEnumData->achFlags[pEnumData->cEntries] = 0;
    88                 pEnumData->aEntries[pEnumData->cEntries++] = pNode->pRight;
     66                pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->pRight);
    8967            }
    9068        } /* while */
     
    9472        while (pEnumData->cEntries > 0)
    9573        {
    96             pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
    97 
     74            KAVLNODECORE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1];
    9875
    9976            /* right */
     
    10178            {
    10279                pEnumData->achFlags[pEnumData->cEntries - 1]++;
    103                 if (pNode->pRight != NULL)
     80                if (pNode->pRight != KAVL_NULL)
    10481                {
    10582                    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);
    10784                    continue;
    10885                }
     
    11390            {
    11491                pEnumData->achFlags[pEnumData->cEntries - 1]++;
    115                 KLOGEXIT(pNode);
    11692                return pNode;
    11793            }
     
    11995            /* left */
    12096            pEnumData->cEntries--;
    121             if (pNode->pLeft != NULL)
     97            if (pNode->pLeft != KAVL_NULL)
    12298            {
    12399                pEnumData->achFlags[pEnumData->cEntries] = 0;
    124                 pEnumData->aEntries[pEnumData->cEntries++] = pNode->pLeft;
     100                pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->pLeft);
    125101            }
    126102        } /* while */
    127103    }
    128104
    129     KLOGEXIT(NULL);
    130105    return NULL;
    131106}
    132107
    133108
    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 */
     118KAVL_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;
    135129
     130    return KAVL_FN(GetNextNode)(pEnumData);
     131}
     132
  • trunk/kStuff/include/k/kAVLTmpl/kAVLGet.h

    r3553 r3555  
    11/* $Id$ */
    22/** @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.
    94 */
    105
    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 */
    1326
    1427
    1528/**
    1629 * Gets a node from the tree (does not remove it!)
     30 *
    1731 * @returns   Pointer to the node holding the given key.
    1832 * @param     ppTree  Pointer to the AVL-tree root node pointer.
    1933 * @param     Key     Key value of the node which is to be found.
    20  * @sketch
    21  * @status    completely implemented.
    22  * @author    knut st. osmundsen
    2334 */
    24 PKAVLNODECORE KLIBCALL KAVL_FN(Get)(PPKAVLNODECORE ppTree, KAVLKEY Key)
     35KAVL_DECL(KAVLNODECORE *) KAVL_FN(Get)(KAVLTREEPTR *ppTree, KAVLKEY Key)
    2536{
    26     KLOGENTRY2("PKAVLNODECORE","PPKAVLNODECORE ppTree, KAVLKEY Key", ppTree, Key);
    27     #ifndef AVL_CMP
    28     register PKAVLNODECORE   pNode = *ppTree;
     37    KAVLNODECORE *pNode;
     38    if (*ppTree == KAVL_NULL)
     39        return NULL;
    2940
    30     while (pNode != NULL && AVL_NE(pNode->Key, Key))
     41    pNode = KAVL_GET_POINTER(ppTree);
     42    while (KAVL_NE(pNode->Key, Key))
    3143    {
    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        }
    3450        else
    35             pNode = pNode->pRight;
     51        {
     52            if (pNode->pRight == KAVL_NULL)
     53                return NULL;
     54            pNode = KAVL_GET_POINTER(&pNode->pRight);
     55        }
    3656    }
    37 
    38     #else
    39 
    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         else
    48             pNode = pNode->pRight;
    49     }
    50 
    51     #endif
    52 
    53     KLOGEXIT(pNode);
    5457    return pNode;
    5558}
    5659
    57 
    58 #endif
  • trunk/kStuff/include/k/kAVLTmpl/kAVLGetBestFit.h

    r3553 r3555  
    11/* $Id$ */
    22/** @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.
    104 */
    115
    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 */
    1426
    1527
    1628/**
    1729 * 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.
    2839 */
    29 PKAVLNODECORE KLIBCALL KAVL_FN(GetBestFit)(PPKAVLNODECORE ppTree, KAVLKEY Key, KBOOL fAbove)
     40KAVL_DECL(KAVLNODECORE *) KAVL_FN(GetBestFit)(KAVLTREEPTR *ppTree, KAVLKEY Key, KBOOL fAbove)
    3041{
    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;
    3744
     45    if (*ppTree == KAVL_NULL)
     46        return NULL;
     47
     48    pNode = KAVL_GET_POINTER(ppTree);
     49    pNodeLast = NULL;
    3850    if (fAbove)
    3951    {   /* 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))
    4553        {
    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))
    5155            {
     56                if (pNode->pLeft == KAVL_NULL)
     57                    return pNode;
    5258                pNodeLast = pNode;
    53                 pNode = pNode->pLeft;
     59                pNode = KAVL_GET_POINTER(&pNode->pLeft);
    5460            }
    5561            else
    56                 pNode = pNode->pRight;
     62            {
     63                if (pNode->pRight == KAVL_NULL)
     64                    return pNodeLast;
     65                pNode = KAVL_GET_POINTER(&pNode->pRight);
     66            }
    5767        }
    5868    }
    5969    else
    6070    {   /* 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))
    6672        {
    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))
    7274            {
    73                 pNodeLast = pNode;
    74                 pNode = pNode->pRight;
     75                if (pNode->pLeft == KAVL_NULL)
     76                    return pNodeLast;
     77                pNode = KAVL_GET_POINTER(&pNode->pLeft);
    7578            }
    7679            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            }
    7886        }
    7987    }
    8088
    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;
    8391}
    8492
    85 
    86 #endif
  • trunk/kStuff/include/k/kAVLTmpl/kAVLGetWithParent.h

    r3553 r3555  
    11/* $Id$ */
    22/** @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.
    94 */
    105
    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 */
    1326
    1427
    1528/**
    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 *
    1732 * @returns   Pointer to the node holding the given key.
    1833 * @param     ppTree    Pointer to the AVL-tree root node pointer.
     
    2035 *                      return. When no node is found, this will hold the last searched node.
    2136 * @param     Key       Key value of the node which is to be found.
    22  * @sketch
    23  * @status    completely implemented.
    24  * @author    knut st. osmundsen
    2537 */
    26 PKAVLNODECORE KLIBCALL KAVL_FN(GetWithParent)(PPKAVLNODECORE ppTree, PPKAVLNODECORE ppParent, KAVLKEY Key)
     38KAVL_DECL(KAVLNODECORE *) KAVL_FN(GetWithParent)(KAVLTREEPTR *ppTree, KAVLNODECORE **ppParent, KAVLKEY Key)
    2739{
    28     KLOGENTRY3("PKAVLNODECORE","PPKAVLNODECORE ppTree, PPKAVLNODECORE ppParent, KAVLKEY Key", ppTree, ppParent, Key);
    29     #ifndef AVL_CMP
     40    register KAVLNODECORE *pNode = KAVL_GET_POINTER_NULL(ppTree);
     41    register KAVLNODECORE *pParent = NULL;
    3042
    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))
    3545    {
    3646        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);
    3949        else
    40             pNode = pNode->pRight;
     50            pNode = KAVL_GET_POINTER_NULL(&pNode->pRight);
    4151    }
    4252
    43     #else
    44 
    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         else
    55             pNode = pNode->pRight;
    56     }
    57 
    58     #endif
    59 
    6053    *ppParent = pParent;
    61     KLOGEXIT(pNode);
    6254    return pNode;
    6355}
    6456
    65 
    66 #endif
    67 
  • trunk/kStuff/include/k/kAVLTmpl/kAVLRemove2.h

    r3553 r3555  
    11/* $Id$ */
    22/** @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.
    94 */
    105
    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 */
    1326
    1427
    1528/**
    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.
    6437 */
    65 PKAVLNODECORE KLIBCALL KAVL_FN(Remove2)(PPKAVLNODECORE ppTree, PKAVLNODECORE pNode)
     38KAVL_DECL(KAVLNODECORE *) KAVL_FN(Remove2)(KAVLTREEPTR *ppTree, KAVLNODECORE *pNode)
    6639{
    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)
    7649    {
    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)
    8854        {
    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         else
    96             ppDeleteNode = &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;
    9763        }
    98         #endif
     64        return NULL;
    9965    }
    10066
    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
    10277    {
    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)
    10593        {
    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);
    15898        }
    15999        else
    160         {
    161             *ppDeleteNode = pDeleteNode->pRight;
    162             AVLStack.cEntries--;
    163         }
     100            KAVL_SET_POINTER(ppTree, pNewUs);
     101    }
     102    return pNode;
    164103
    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;
    167114
    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
    175118}
    176119
    177 #endif
  • trunk/kStuff/include/k/kAVLTmpl/kAVLRemoveBestFit.h

    r3553 r3555  
    11/* $Id$ */
    22/** @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.
    104 */
    115
    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 */
    1426
    1527
    1628/**
    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.
    3040 */
    31 PKAVLNODECORE KLIBCALL KAVL_FN(RemoveBestFit)(PPKAVLNODECORE ppTree, KAVLKEY Key, KBOOL fAbove)
     41KAVL_DECL(KAVLNODECORE *) KAVL_FN(RemoveBestFit)(KAVLTREEPTR *ppTree, KAVLKEY Key, KBOOL fAbove)
    3242{
    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)
    4753        {
    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;
    5957        }
     58#endif
     59        pNode = KAVL_FN(Remove)(ppTree, pNode->Key);
    6060    }
    61     else
    62     {   /* pNode->Key <= Key */
    63         #ifndef AVL_CMP
    64         while (pNode != NULL && AVL_NE(pNode->Key, Key))
    65         #else
    66         while (pNode != NULL && (iDiff = AVL_CMP(pNode->Key, Key)) != 0)
    67         #endif
    68         {
    69             #ifndef AVL_CMP
    70             if (AVL_L(pNode->Key, Key))
    71             #else
    72             if (iDiff < 0)
    73             #endif
    74             {
    75                 pNodeLast = pNode;
    76                 pNode = pNode->pRight;
    77             }
    78             else
    79                 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 first
    86      * and return one of them before doing an expensive remove operation
    87      * 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_ALLOWED
    97     if (pNode->pList)
    98     {
    99         pNodeLast = pNode->pList;
    100         pNode->pList = pNodeLast->pList;
    101         KLOGEXIT(pNodeLast);
    102         return pNodeLast;
    103     }
    104     #endif
    105     pNode = KAVL_FN(Remove)(ppTree, pNode->Key);
    106     KLOGEXIT(pNode);
    10761    return pNode;
    10862}
    10963
    110 
    111 #endif
Note: See TracChangeset for help on using the changeset viewer.