示例#1
0
Bool SplayTreeNeighbours(Tree *leftReturn, Tree *rightReturn,
                         SplayTree splay, TreeKey key)
{
  SplayStateStruct stateStruct;
  Bool found;
  Compare cmp;
#ifdef SPLAY_DEBUG
  Count count = SplayDebugCount(splay);
#endif


  AVERT(SplayTree, splay);
  AVER(leftReturn != NULL);
  AVER(rightReturn != NULL);

  if (SplayTreeIsEmpty(splay)) {
    *leftReturn = *rightReturn = TreeEMPTY;
    return TRUE;
  }

  cmp = SplaySplit(&stateStruct, splay, key, splay->compare);

  switch (cmp) {
  default:
    NOTREACHED;
    /* defensive fall-through */
  case CompareEQUAL:
    found = FALSE;
    break;

  case CompareLESS:
    AVER(!TreeHasLeft(stateStruct.middle));
    *rightReturn = stateStruct.middle;
    *leftReturn = stateStruct.leftLast;
    found = TRUE;
    break;

  case CompareGREATER:
    AVER(!TreeHasRight(stateStruct.middle));
    *leftReturn = stateStruct.middle;
    *rightReturn = stateStruct.rightFirst;
    found = TRUE;
    break;
  }

  SplayAssemble(splay, &stateStruct);
  SplayTreeSetRoot(splay, stateStruct.middle);

#ifdef SPLAY_DEBUG
  AVER(count == SplayDebugCount(splay));
#endif

  return found;
}
static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
                       void *key, SplayCompareMethod compareMethod) {
    /* The sides structure avoids a boundary case in SplayLink* */
    SplayNodeStruct sides; /* rightTop and leftTop */
    SplayNode top, leftLast, rightFirst;
    Bool found;
    Compare compareTop;

    AVERT(SplayTree, tree);
    AVER(nodeReturn != NULL);
    AVER(FUNCHECK(compareMethod));

    top = SplayTreeRoot(tree); /* will be copied back at end */

    if (top == NULL) {
        *nodeReturn = NULL;
        return FALSE;
    }

    /* short-circuit case where node is already top */
    compareTop = (*compareMethod)(key, top);
    if (compareTop == CompareEQUAL) {
        *nodeReturn = top;
        return TRUE;
    }

    SplayNodeInit(&sides); /* left and right trees now NULL */
    leftLast = &sides;
    rightFirst = &sides;

    while(TRUE) {
        /* compareTop is already initialised above. */
        switch(compareTop) {

        case CompareLESS: {
            SplayNode topLeft = SplayNodeLeftChild(top);
            if (topLeft == NULL) {
                found = FALSE;
                goto assemble;
            } else {
                Compare compareTopLeft = (*compareMethod)(key, topLeft);

                switch(compareTopLeft) {

                case CompareEQUAL: {                 /* zig */
                    SplayLinkRight(&top, &rightFirst);
                    found = TRUE;
                    goto assemble;
                    } /* break; */

                case CompareLESS: {                  /* zig-zig */
                    if (SplayNodeLeftChild(topLeft) == NULL)
                        goto terminalZig;
                    SplayRotateRight(&top, tree);
                    SplayLinkRight(&top, &rightFirst);
                }
                break;

                case CompareGREATER: {               /* zig-zag */
                    if (SplayNodeRightChild(topLeft) == NULL)
                        goto terminalZig;
                    SplayLinkRight(&top, &rightFirst);
                    SplayLinkLeft(&top, &leftLast);
                }
                break;

                default: {
                    NOTREACHED;
                }
                break;
                }
            }
        }
        break;

        case CompareGREATER: {
            SplayNode topRight = SplayNodeRightChild(top);
            if (topRight == NULL) {
                found = FALSE;
                goto assemble;
            } else {
                Compare compareTopRight = (*compareMethod)(key, topRight);

                switch(compareTopRight) {

                case CompareEQUAL: {                 /* zag */
                    SplayLinkLeft(&top, &leftLast);
                    found = TRUE;
                    goto assemble;
                    } /* break; */

                case CompareGREATER: {               /* zag-zag */
                    if (SplayNodeRightChild(topRight) == NULL)
                        goto terminalZag;
                    SplayRotateLeft(&top, tree);
                    SplayLinkLeft(&top, &leftLast);
                }
                break;

                case CompareLESS: {                  /* zag-zig */
                    if (SplayNodeLeftChild(topRight) == NULL)
                        goto terminalZag;
                    SplayLinkLeft(&top, &leftLast);
                    SplayLinkRight(&top, &rightFirst);
                }
                break;

                default: {
                    NOTREACHED;
                }
                break;
                }
            }
        }
        break;

        case CompareEQUAL: {
            found = TRUE;
            goto assemble;
            } /* break; */

        default: {
            NOTREACHED;
        }
        break;
        }
        compareTop = (*compareMethod)(key, top);
    } /* end while(TRUE) */

terminalZig:
    SplayLinkRight(&top, &rightFirst);
    found = FALSE;
    goto assemble;

terminalZag:
    SplayLinkLeft(&top, &leftLast);
    found = FALSE;
    goto assemble;

assemble:
    SplayAssemble(tree, top,
                  SplayNodeRightChild(&sides), leftLast,
                  SplayNodeLeftChild(&sides), rightFirst);

    SplayTreeSetRoot(tree, top);
    *nodeReturn = top;

    return found;
}