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; }