static Tree SplayZagZagRev(Tree middle, Tree *leftLastIO) { Tree child; AVERT_CRITICAL(Tree, middle); AVER_CRITICAL(leftLastIO != NULL); AVERT_CRITICAL(Tree, *leftLastIO); child = TreeRight(middle); TreeSetRight(middle, TreeRight(*leftLastIO)); TreeSetRight(*leftLastIO, TreeLeft(middle)); TreeSetLeft(middle, *leftLastIO); *leftLastIO = middle; return child; }
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; }
Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay, SplayTestNodeFunction testNode, SplayTestTreeFunction testTree, void *closureP, Size closureS) { SplayFindClosureStruct closureStruct; Bool found; AVER(nodeReturn != NULL); AVERT(SplayTree, splay); AVER(FUNCHECK(testNode)); AVER(FUNCHECK(testTree)); if (SplayTreeIsEmpty(splay) || !testTree(splay, SplayTreeRoot(splay), closureP, closureS)) return FALSE; /* no suitable nodes in tree */ closureStruct.p = closureP; closureStruct.s = closureS; closureStruct.testNode = testNode; closureStruct.testTree = testTree; closureStruct.splay = splay; closureStruct.found = FALSE; found = SplaySplay(splay, &closureStruct, SplayFindFirstCompare) == CompareEQUAL && closureStruct.found; while (!found) { Tree oldRoot, newRoot; /* FIXME: Rename to "seen" and "not yet seen" or something. */ oldRoot = SplayTreeRoot(splay); newRoot = TreeRight(oldRoot); if (newRoot == TreeEMPTY || !(*testTree)(splay, newRoot, closureP, closureS)) return FALSE; /* no suitable nodes in the rest of the tree */ /* Temporarily chop off the left half-tree, inclusive of root, so that the search excludes any nodes we've seen already. */ SplayTreeSetRoot(splay, newRoot); TreeSetRight(oldRoot, TreeEMPTY); found = SplaySplay(splay, &closureStruct, SplayFindFirstCompare) == CompareEQUAL && closureStruct.found; /* Restore the left tree, then rotate left so that the node we just splayed is at the root. Update both. */ newRoot = SplayTreeRoot(splay); TreeSetRight(oldRoot, newRoot); SplayTreeSetRoot(splay, oldRoot); TreeRotateLeft(&splay->root); splay->updateNode(splay, oldRoot); splay->updateNode(splay, newRoot); } *nodeReturn = SplayTreeRoot(splay); return TRUE; }
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; } }
static Tree stepDownRight(Tree node, Tree *parentIO) { Tree parent = *parentIO; Tree child = TreeRight(node); TreeSetRight(node, parent); *parentIO = node; return child; }
static Tree stepUpLeft(Tree node, Tree *parentIO) { Tree parent = *parentIO; Tree grandparent = TreeRight(parent); TreeSetRight(parent, node); *parentIO = grandparent; return parent; }
static Tree SplayZag(Tree middle, Tree *leftLastIO, Tree *leftPrevReturn) { AVERT_CRITICAL(Tree, middle); AVER_CRITICAL(leftLastIO != NULL); AVERT_CRITICAL(Tree, *leftLastIO); TreeSetRight(*leftLastIO, middle); *leftPrevReturn = *leftLastIO; *leftLastIO = middle; return TreeRight(middle); }
void SplayDebugUpdate(SplayTree splay, Tree tree) { AVERT(SplayTree, splay); AVERT(Tree, tree); if (tree == TreeEMPTY) return; SplayDebugUpdate(splay, TreeLeft(tree)); SplayDebugUpdate(splay, TreeRight(tree)); splay->updateNode(splay, tree); }
Bool SplayTreeInsert(SplayTree splay, Tree node) { Tree neighbour; AVERT(SplayTree, splay); AVERT(Tree, node); AVER(TreeLeft(node) == TreeEMPTY); AVER(TreeRight(node) == TreeEMPTY); if (SplayTreeIsEmpty(splay)) { SplayTreeSetRoot(splay, node); return TRUE; } switch (SplaySplay(splay, splay->nodeKey(node), splay->compare)) { default: NOTREACHED; /* fall through */ case CompareEQUAL: /* duplicate node */ return FALSE; case CompareGREATER: /* left neighbour is at root */ neighbour = SplayTreeRoot(splay); SplayTreeSetRoot(splay, node); TreeSetRight(node, TreeRight(neighbour)); TreeSetLeft(node, neighbour); TreeSetRight(neighbour, TreeEMPTY); break; case CompareLESS: /* right neighbour is at root */ neighbour = SplayTreeRoot(splay); SplayTreeSetRoot(splay, node); TreeSetLeft(node, TreeLeft(neighbour)); TreeSetRight(node, neighbour); TreeSetLeft(neighbour, TreeEMPTY); break; } splay->updateNode(splay, neighbour); splay->updateNode(splay, node); return TRUE; }
static Tree SplayZigZig(Tree middle, Tree *rightFirstIO, Tree rightNext) { AVERT_CRITICAL(Tree, middle); AVER_CRITICAL(rightFirstIO != NULL); AVERT_CRITICAL(Tree, *rightFirstIO); TreeSetLeft(*rightFirstIO, TreeRight(middle)); TreeSetRight(middle, *rightFirstIO); TreeSetLeft(rightNext, middle); *rightFirstIO = middle; return TreeLeft(middle); }
static Tree SplayZigZigRev(Tree middle, Tree *rightFirstIO) { Tree child; AVERT_CRITICAL(Tree, middle); AVER_CRITICAL(rightFirstIO != NULL); AVERT_CRITICAL(Tree, *rightFirstIO); child = TreeLeft(middle); TreeSetLeft(middle, TreeLeft(*rightFirstIO)); TreeSetLeft(*rightFirstIO, TreeRight(middle)); TreeSetRight(middle, *rightFirstIO); *rightFirstIO = middle; return child; }
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 Count TreeDebugCountBetween(Tree node, TreeCompare compare, TreeKeyMethod key, TreeKey min, TreeKey max) { if (node == TreeEMPTY) return 0; AVERT(Tree, node); AVER(min == NULL || compare(node, min) != CompareGREATER); AVER(max == NULL || compare(node, max) != CompareLESS); return TreeDebugCountBetween(TreeLeft(node), compare, key, min, key(node)) + 1 + TreeDebugCountBetween(TreeRight(node), compare, key, key(node), max); }
static Tree SplayUpdateRightSpine(SplayTree splay, Tree node, Tree child) { AVERT_CRITICAL(SplayTree, splay); AVERT_CRITICAL(Tree, node); AVERT_CRITICAL(Tree, child); while (node != TreeEMPTY) { Tree parent = TreeRight(node); TreeSetRight(node, child); /* un-reverse pointer */ splay->updateNode(splay, node); child = node; node = parent; } return child; }
void TreeRotateRight(Tree *treeIO) { Tree tree, left; AVER(treeIO != NULL); tree = *treeIO; AVERT(Tree, tree); left = TreeLeft(tree); AVERT(Tree, left); TreeSetLeft(*treeIO, TreeRight(left)); TreeSetRight(left, *treeIO); *treeIO = left; }
void TreeRotateLeft(Tree *treeIO) { Tree tree, right; AVER(treeIO != NULL); tree = *treeIO; AVERT(Tree, tree); right = TreeRight(tree); AVERT(Tree, right); TreeSetRight(tree, TreeLeft(right)); TreeSetLeft(right, tree); *treeIO = right; }
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; }
Tree TreeReverseRightSpine(Tree tree) { Tree node, parent; AVERT(Tree, tree); parent = TreeEMPTY; node = tree; while (node != TreeEMPTY) { Tree child = TreeRight(node); TreeSetRight(node, parent); parent = node; node = child; } return parent; }
static void SplayAssembleRev(SplayTree splay, SplayState state) { Tree left, right; AVERT(SplayTree, splay); AVER(state->middle != TreeEMPTY); left = TreeLeft(state->middle); left = SplayUpdateRightSpine(splay, state->leftLast, left); TreeSetLeft(state->middle, left); right = TreeRight(state->middle); right = SplayUpdateLeftSpine(splay, state->rightFirst, right); TreeSetRight(state->middle, right); splay->updateNode(splay, state->middle); }
static void SplayAssembleDown(SplayTree splay, SplayState state) { AVERT(SplayTree, splay); AVER(state->middle != TreeEMPTY); AVER(!SplayHasUpdate(splay)); if (state->left != TreeEMPTY) { AVER_CRITICAL(state->leftLast != TreeEMPTY); TreeSetRight(state->leftLast, TreeLeft(state->middle)); TreeSetLeft(state->middle, state->left); } if (state->right != TreeEMPTY) { AVER_CRITICAL(state->rightFirst != TreeEMPTY); TreeSetLeft(state->rightFirst, TreeRight(state->middle)); TreeSetRight(state->middle, state->right); } }
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; }