Bool TreeTraverse(Tree tree, TreeCompare compare, TreeKeyMethod key, TreeVisitor visit, void *closureP, Size closureS) { Tree parent, node; AVERT(Tree, tree); AVER(FUNCHECK(visit)); /* closureP, closureS arbitrary */ parent = TreeEMPTY; node = tree; if (node == TreeEMPTY) return TRUE; down: if (TreeHasLeft(node)) { node = stepDownLeft(node, &parent); AVER(compare(parent, key(node)) == CompareLESS); goto down; } if (!visit(node, closureP, closureS)) goto abort; if (TreeHasRight(node)) { node = stepDownRight(node, &parent); AVER(compare(parent, key(node)) != CompareLESS); goto down; } up: if (parent == TreeEMPTY) return TRUE; if (compare(parent, key(node)) != CompareLESS) { node = stepUpLeft(node, &parent); goto up; } node = stepUpRight(node, &parent); if (!visit(node, closureP, closureS)) goto abort; if (!TreeHasRight(node)) goto up; node = stepDownRight(node, &parent); goto down; abort: if (parent == TreeEMPTY) return FALSE; if (compare(parent, key(node)) != CompareLESS) node = stepUpLeft(node, &parent); else node = stepUpRight(node, &parent); goto abort; }
static Tree SplayTreeSuccessor(SplayTree splay) { Tree oldRoot, newRoot; AVERT(SplayTree, splay); AVER(!SplayTreeIsEmpty(splay)); oldRoot = SplayTreeRoot(splay); if (!TreeHasRight(oldRoot)) return TreeEMPTY; /* No successor */ /* temporarily chop off the left half-tree, inclusive of root */ SplayTreeSetRoot(splay, TreeRight(oldRoot)); TreeSetRight(oldRoot, TreeEMPTY); (void)SplaySplay(splay, NULL, compareLess); newRoot = SplayTreeRoot(splay); AVER(newRoot != TreeEMPTY); AVER(TreeLeft(newRoot) == TreeEMPTY); TreeSetLeft(newRoot, oldRoot); splay->updateNode(splay, oldRoot); splay->updateNode(splay, newRoot); return newRoot; }
static Compare SplayFindLastCompare(Tree node, TreeKey key) { SplayFindClosure my; SplayTestNodeFunction testNode; SplayTestTreeFunction testTree; void *testClosure; SplayTree splay; AVERT_CRITICAL(Tree, node); AVER_CRITICAL(key != NULL); /* Lift closure values into variables so that they aren't aliased by calls to the test functions. */ my = (SplayFindClosure)key; testClosure = my->testClosure; testNode = my->testNode; testTree = my->testTree; splay = my->splay; if (TreeHasRight(node) && (*testTree)(splay, TreeRight(node), testClosure)) { return CompareGREATER; } else if ((*testNode)(splay, node, testClosure)) { my->found = TRUE; return CompareEQUAL; } else { /* See SplayFindFirstCompare. */ if (TreeHasLeft(node) && !(*testTree)(splay, TreeLeft(node), testClosure)) { my->found = FALSE; return CompareEQUAL; } return CompareLESS; } }
void SplayNodeInit(SplayTree splay, Tree node) { AVERT(SplayTree, splay); AVERT(Tree, node); AVER(!TreeHasLeft(node)); /* otherwise, call SplayNodeRefresh */ AVER(!TreeHasRight(node)); /* otherwise, call SplayNodeRefresh */ splay->updateNode(splay, node); }
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; }
Bool SplayTreeDelete(SplayTree splay, Tree node) { Tree leftLast; Compare cmp; AVERT(SplayTree, splay); AVERT(Tree, node); if (SplayTreeIsEmpty(splay)) return FALSE; cmp = SplaySplay(splay, splay->nodeKey(node), splay->compare); AVER(cmp != CompareEQUAL || SplayTreeRoot(splay) == node); if (cmp != CompareEQUAL) { return FALSE; } else if (!TreeHasLeft(node)) { SplayTreeSetRoot(splay, TreeRight(node)); TreeClearRight(node); } else if (!TreeHasRight(node)) { SplayTreeSetRoot(splay, TreeLeft(node)); TreeClearLeft(node); } else { Tree rightHalf = TreeRight(node); TreeClearRight(node); SplayTreeSetRoot(splay, TreeLeft(node)); TreeClearLeft(node); (void)SplaySplay(splay, NULL, compareGreater); leftLast = SplayTreeRoot(splay); AVER(leftLast != TreeEMPTY); AVER(!TreeHasRight(leftLast)); TreeSetRight(leftLast, rightHalf); splay->updateNode(splay, leftLast); } TreeFinish(node); return TRUE; }
static Res SplayNodeDescribe(Tree node, mps_lib_FILE *stream, TreeDescribeFunction nodeDescribe) { Res res; if (!TreeCheck(node)) return ResFAIL; if (stream == NULL) return ResFAIL; if (nodeDescribe == NULL) return ResFAIL; res = WriteF(stream, 0, "( ", NULL); if (res != ResOK) return res; if (TreeHasLeft(node)) { res = SplayNodeDescribe(TreeLeft(node), stream, nodeDescribe); if (res != ResOK) return res; res = WriteF(stream, 0, " / ", NULL); if (res != ResOK) return res; } res = (*nodeDescribe)(node, stream); if (res != ResOK) return res; if (TreeHasRight(node)) { res = WriteF(stream, 0, " \\ ", NULL); if (res != ResOK) return res; res = SplayNodeDescribe(TreeRight(node), stream, nodeDescribe); if (res != ResOK) return res; } res = WriteF(stream, 0, " )", NULL); if (res != ResOK) return res; return ResOK; }
static Compare SplayFindFirstCompare(Tree node, TreeKey key) { SplayFindClosure closure; void *closureP; Size closureS; SplayTestNodeFunction testNode; SplayTestTreeFunction testTree; SplayTree splay; AVERT(Tree, node); AVER(key != NULL); /* Lift closure values into variables so that they aren't aliased by calls to the test functions. */ closure = (SplayFindClosure)key; closureP = closure->p; closureS = closure->s; testNode = closure->testNode; testTree = closure->testTree; splay = closure->splay; if (TreeHasLeft(node) && (*testTree)(splay, TreeLeft(node), closureP, closureS)) { return CompareLESS; } else if ((*testNode)(splay, node, closureP, closureS)) { closure->found = TRUE; return CompareEQUAL; } else { /* If there's a right subtree but it doesn't satisfy the tree test then we want to terminate the splay right now. SplaySplay will return TRUE, so the caller must check closure->found to find out whether the result node actually satisfies testNode. */ if (TreeHasRight(node) && !(*testTree)(splay, TreeRight(node), closureP, closureS)) { closure->found = FALSE; return CompareEQUAL; } return CompareGREATER; } }
static Compare SplayFindLastCompare(Tree node, TreeKey key) { SplayFindClosure closure; void *closureP; Size closureS; SplayTestNodeFunction testNode; SplayTestTreeFunction testTree; SplayTree splay; AVERT(Tree, node); AVER(key != NULL); /* Lift closure values into variables so that they aren't aliased by calls to the test functions. */ closure = (SplayFindClosure)key; closureP = closure->p; closureS = closure->s; testNode = closure->testNode; testTree = closure->testTree; splay = closure->splay; if (TreeHasRight(node) && (*testTree)(splay, TreeRight(node), closureP, closureS)) { return CompareGREATER; } else if ((*testNode)(splay, node, closureP, closureS)) { closure->found = TRUE; return CompareEQUAL; } else { /* See SplayFindFirstCompare. */ if (TreeHasLeft(node) && !(*testTree)(splay, TreeLeft(node), closureP, closureS)) { closure->found = FALSE; return CompareEQUAL; } return CompareLESS; } }
static Compare SplaySplitRev(SplayStateStruct *stateReturn, SplayTree splay, TreeKey key, TreeCompareFunction compare) { Tree middle, leftLast, rightFirst; Compare cmp; AVERT(SplayTree, splay); AVER(FUNCHECK(compare)); AVER(!SplayTreeIsEmpty(splay)); leftLast = TreeEMPTY; rightFirst = TreeEMPTY; middle = SplayTreeRoot(splay); for (;;) { cmp = compare(middle, key); switch(cmp) { default: NOTREACHED; /* defensive fall-through */ case CompareEQUAL: goto stop; case CompareLESS: if (!TreeHasLeft(middle)) goto stop; middle = SplayZigRev(middle, &rightFirst); cmp = compare(middle, key); switch(cmp) { default: NOTREACHED; /* defensive fall-through */ case CompareEQUAL: goto stop; case CompareLESS: if (!TreeHasLeft(middle)) goto stop; middle = SplayZigZigRev(middle, &rightFirst); splay->updateNode(splay, TreeRight(rightFirst)); break; case CompareGREATER: if (!TreeHasRight(middle)) goto stop; middle = SplayZagRev(middle, &leftLast); break; } break; case CompareGREATER: if (!TreeHasRight(middle)) goto stop; middle = SplayZagRev(middle, &leftLast); cmp = compare(middle, key); switch(cmp) { default: NOTREACHED; /* defensive fall-through */ case CompareEQUAL: goto stop; case CompareGREATER: if (!TreeHasRight(middle)) goto stop; middle = SplayZagZagRev(middle, &leftLast); splay->updateNode(splay, TreeLeft(leftLast)); break; case CompareLESS: if (!TreeHasLeft(middle)) goto stop; middle = SplayZigRev(middle, &rightFirst); break; } break; } } stop: stateReturn->middle = middle; stateReturn->leftLast = leftLast; stateReturn->rightFirst = rightFirst; return cmp; }
static Compare SplaySplitDown(SplayStateStruct *stateReturn, SplayTree splay, TreeKey key, TreeCompareFunction compare) { TreeStruct sentinel; Tree middle, leftLast, rightFirst, leftPrev, rightNext; Compare cmp; AVERT(SplayTree, splay); AVER(FUNCHECK(compare)); AVER(!SplayTreeIsEmpty(splay)); AVER(!SplayHasUpdate(splay)); TreeInit(&sentinel); leftLast = &sentinel; rightFirst = &sentinel; middle = SplayTreeRoot(splay); for (;;) { cmp = compare(middle, key); switch(cmp) { default: NOTREACHED; /* defensive fall-through */ case CompareEQUAL: goto stop; case CompareLESS: if (!TreeHasLeft(middle)) goto stop; middle = SplayZig(middle, &rightFirst, &rightNext); cmp = compare(middle, key); switch(cmp) { default: NOTREACHED; /* defensive fall-through */ case CompareEQUAL: goto stop; case CompareLESS: if (!TreeHasLeft(middle)) goto stop; middle = SplayZigZig(middle, &rightFirst, rightNext); break; case CompareGREATER: if (!TreeHasRight(middle)) goto stop; middle = SplayZag(middle, &leftLast, &leftPrev); break; } break; case CompareGREATER: if (!TreeHasRight(middle)) goto stop; middle = SplayZag(middle, &leftLast, &leftPrev); cmp = compare(middle, key); switch(cmp) { default: NOTREACHED; /* defensive fall-through */ case CompareEQUAL: goto stop; case CompareGREATER: if (!TreeHasRight(middle)) goto stop; middle = SplayZagZag(middle, &leftLast, leftPrev); break; case CompareLESS: if (!TreeHasLeft(middle)) goto stop; middle = SplayZig(middle, &rightFirst, &rightNext); break; } break; } } stop: stateReturn->middle = middle; stateReturn->left = TreeRight(&sentinel); stateReturn->leftLast = leftLast == &sentinel ? TreeEMPTY : leftLast; stateReturn->right = TreeLeft(&sentinel); stateReturn->rightFirst = rightFirst == &sentinel ? TreeEMPTY : rightFirst; return cmp; }