Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream, Count depth, TreeDescribeFunction nodeDescribe) { Res res; if (!TESTT(SplayTree, splay)) return ResFAIL; if (stream == NULL) return ResFAIL; if (nodeDescribe == NULL) return ResFAIL; res = WriteF(stream, depth, "Splay $P {\n", (WriteFP)splay, " compare $F\n", (WriteFF)splay->compare, " nodeKey $F\n", (WriteFF)splay->nodeKey, " updateNode $F\n", (WriteFF)splay->updateNode, NULL); if (res != ResOK) return res; if (SplayTreeRoot(splay) != TreeEMPTY) { res = WriteF(stream, depth, " tree ", NULL); if (res != ResOK) return res; res = SplayNodeDescribe(SplayTreeRoot(splay), stream, nodeDescribe); if (res != ResOK) return res; } res = WriteF(stream, depth, "\n} Splay $P\n", (WriteFP)splay, NULL); return res; }
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; }
Bool SplayFindLast(Tree *nodeReturn, SplayTree splay, SplayTestNodeFunction testNode, SplayTestTreeFunction testTree, void *testClosure) { SplayFindClosureStruct closureStruct; Bool found; AVER_CRITICAL(nodeReturn != NULL); AVERT_CRITICAL(SplayTree, splay); AVER_CRITICAL(FUNCHECK(testNode)); AVER_CRITICAL(FUNCHECK(testTree)); if (SplayTreeIsEmpty(splay) || !testTree(splay, SplayTreeRoot(splay), testClosure)) return FALSE; /* no suitable nodes in tree */ closureStruct.testClosure = testClosure; closureStruct.testNode = testNode; closureStruct.testTree = testTree; closureStruct.splay = splay; found = SplaySplay(splay, &closureStruct, SplayFindLastCompare) == CompareEQUAL && closureStruct.found; while (!found) { Tree oldRoot, newRoot; oldRoot = SplayTreeRoot(splay); newRoot = TreeLeft(oldRoot); if (newRoot == TreeEMPTY || !(*testTree)(splay, newRoot, testClosure)) return FALSE; /* no suitable nodes in the rest of the tree */ /* Temporarily chop off the right half-tree, inclusive of root, so that the search excludes any nodes we've seen already. */ SplayTreeSetRoot(splay, newRoot); TreeSetLeft(oldRoot, TreeEMPTY); found = SplaySplay(splay, &closureStruct, SplayFindLastCompare) == CompareEQUAL && closureStruct.found; /* Restore the right tree, then rotate right so that the node we just splayed is at the root. Update both. */ newRoot = SplayTreeRoot(splay); TreeSetLeft(oldRoot, newRoot); SplayTreeSetRoot(splay, oldRoot); TreeRotateRight(&splay->root); splay->updateNode(splay, oldRoot); splay->updateNode(splay, newRoot); } *nodeReturn = SplayTreeRoot(splay); return TRUE; }
Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree, SplayTestNodeMethod testNode, SplayTestTreeMethod testTree, void *closureP, unsigned long closureS) { SplayNode node; SplayFindClosureStruct closureStruct; AVER(nodeReturn != NULL); AVERT(SplayTree, tree); AVER(FUNCHECK(testNode)); AVER(FUNCHECK(testTree)); node = SplayTreeRoot(tree); if (node == NULL || !(*testTree)(tree, node, closureP, closureS)) return FALSE; /* no suitable nodes in tree */ closureStruct.p = closureP; closureStruct.s = closureS; closureStruct.testNode = testNode; closureStruct.testTree = testTree; closureStruct.tree = tree; if (SplaySplay(&node, tree, (void *)&closureStruct, &SplayFindLastCompare)) { *nodeReturn = node; return TRUE; } else { return FALSE; } }
static SplayNode SplayTreeSuccessor(SplayTree tree, void *key) { SplayNode oldRoot, newRoot; AVERT(SplayTree, tree); oldRoot = SplayTreeRoot(tree); AVERT(SplayNode, oldRoot); if (SplayNodeRightChild(oldRoot) == NULL) { newRoot = NULL; /* No successor */ } else { /* temporarily chop off the left half-tree, inclusive of root */ SplayTreeSetRoot(tree, SplayNodeRightChild(oldRoot)); SplayNodeSetRightChild(oldRoot, NULL); if (SplaySplay(&newRoot, tree, key, tree->compare)) { NOTREACHED; /* Another matching node found */ } else { AVER(SplayNodeLeftChild(newRoot) == NULL); SplayNodeSetLeftChild(newRoot, oldRoot); } if (tree->updateNode != NULL) { SplayNodeUpdate(tree, oldRoot); SplayNodeUpdate(tree, newRoot); } } return newRoot; }
static Compare SplaySplay(SplayTree splay, TreeKey key, TreeCompareFunction compare) { Compare cmp; SplayStateStruct stateStruct; #ifdef SPLAY_DEBUG Count count = SplayDebugCount(splay); #endif /* Short-circuit common cases. Splay trees often bring recently acccessed nodes to the root. */ if (SplayTreeIsEmpty(splay) || compare(SplayTreeRoot(splay), key) == CompareEQUAL) return CompareEQUAL; if (SplayHasUpdate(splay)) { cmp = SplaySplitRev(&stateStruct, splay, key, compare); SplayAssembleRev(splay, &stateStruct); } else { cmp = SplaySplitDown(&stateStruct, splay, key, compare); SplayAssembleDown(splay, &stateStruct); } SplayTreeSetRoot(splay, stateStruct.middle); #ifdef SPLAY_DEBUG AVER(count == SplayDebugCount(splay)); #endif return cmp; }
Res SplayTreeInsert(SplayTree tree, SplayNode node, void *key) { SplayNode neighbour; AVERT(SplayTree, tree); AVERT(SplayNode, node); AVER(SplayNodeLeftChild(node) == NULL); AVER(SplayNodeRightChild(node) == NULL); if (SplayTreeRoot(tree) == NULL) { SplayTreeSetRoot(tree, node); } else if (SplaySplay(&neighbour, tree, key, tree->compare)) { return ResFAIL; } else { AVER(SplayTreeRoot(tree) == neighbour); switch(SplayCompare(tree, key, neighbour)) { case CompareGREATER: { /* left neighbour */ SplayTreeSetRoot(tree, node); SplayNodeSetRightChild(node, SplayNodeRightChild(neighbour)); SplayNodeSetLeftChild(node, neighbour); SplayNodeSetRightChild(neighbour, NULL); } break; case CompareLESS: { /* right neighbour */ SplayTreeSetRoot(tree, node); SplayNodeSetLeftChild(node, SplayNodeLeftChild(neighbour)); SplayNodeSetRightChild(node, neighbour); SplayNodeSetLeftChild(neighbour, NULL); } break; case CompareEQUAL: default: { NOTREACHED; } break; } if (tree->updateNode != NULL) { SplayNodeUpdate(tree, neighbour); SplayNodeUpdate(tree, node); } } return ResOK; }
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; }
Bool SplayTreeFind(Tree *nodeReturn, SplayTree splay, TreeKey key) { AVERT(SplayTree, splay); AVER(nodeReturn != NULL); if (SplayTreeIsEmpty(splay)) return FALSE; if (SplaySplay(splay, key, splay->compare) != CompareEQUAL) return FALSE; *nodeReturn = SplayTreeRoot(splay); return TRUE; }
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; }
void SplayNodeRefresh(SplayTree splay, Tree node) { Compare cmp; AVERT(SplayTree, splay); AVERT(Tree, node); AVER(!SplayTreeIsEmpty(splay)); /* must contain node, at least */ cmp = SplaySplay(splay, splay->nodeKey(node), splay->compare); AVER(cmp == CompareEQUAL); AVER(SplayTreeRoot(splay) == node); splay->updateNode(splay, node); }
SplayNode SplayTreeFirst(SplayTree tree, void *zeroKey) { SplayNode node; AVERT(SplayTree, tree); if (SplayTreeRoot(tree) == NULL) { node = NULL; } else if (SplaySplay(&node, tree, zeroKey, tree->compare)) { NOTREACHED; } else { AVER(SplayNodeLeftChild(node) == NULL); } return node; }
Bool SplayRoot(SplayNode *nodeReturn, SplayTree tree) { SplayNode node; AVER(nodeReturn != NULL); AVERT(SplayTree, tree); node = SplayTreeRoot(tree); if (node == NULL) return FALSE; else { *nodeReturn = node; return TRUE; } }
Res SplayTreeDescribe(SplayTree tree, mps_lib_FILE *stream, SplayNodeDescribeMethod nodeDescribe) { Res res; #if defined(AVER_AND_CHECK) if (!SplayTreeCheck(tree)) return ResFAIL; if (stream == NULL) return ResFAIL; if (!FUNCHECK(nodeDescribe)) return ResFAIL; #endif res = WriteF(stream, "Splay $P {\n", (WriteFP)tree, " compare $F\n", (WriteFF)tree->compare, NULL); if (res != ResOK) return res; if (SplayTreeRoot(tree) != NULL) { res = SplayNodeDescribe(SplayTreeRoot(tree), stream, nodeDescribe); if (res != ResOK) return res; } res = WriteF(stream, "\n}\n", NULL); return res; }
Tree SplayTreeFirst(SplayTree splay) { Tree node; AVERT(SplayTree, splay); if (SplayTreeIsEmpty(splay)) return TreeEMPTY; (void)SplaySplay(splay, NULL, compareLess); node = SplayTreeRoot(splay); AVER(node != TreeEMPTY); AVER(TreeLeft(node) == TreeEMPTY); return node; }
Tree SplayTreeNext(SplayTree splay, TreeKey oldKey) { AVERT(SplayTree, splay); if (SplayTreeIsEmpty(splay)) return TreeEMPTY; /* Make old node the root. Probably already is. We don't mind if the node has been deleted, or replaced by a node with the same key. */ switch (SplaySplay(splay, oldKey, splay->compare)) { default: NOTREACHED; /* defensive fall-through */ case CompareLESS: return SplayTreeRoot(splay); case CompareGREATER: case CompareEQUAL: return SplayTreeSuccessor(splay); } }
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; }
Count SplayDebugCount(SplayTree splay) { AVERT(SplayTree, splay); return TreeDebugCount(SplayTreeRoot(splay), splay->compare, splay->nodeKey); }
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; }