3 * Insertion and removal for splay trees
5 * (c) 2024 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Xyla, a library of binary trees.
12 * Xyla is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU Lesser General Public License as published by the
14 * Free Software Foundation; either version 3 of the License, or (at your
15 * option) any later version.
17 * Xyla is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20 * License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with Xyla. If not, see <https://www.gnu.org/licenses/>.
26 /*----- Header files ------------------------------------------------------*/
31 /*----- Main code ---------------------------------------------------------*/
33 int xyla_splay_insert(struct xyla_bt_nodecls *cls,
34 struct xyla_splay_path *path,
35 struct xyla_splay_node *node)
37 /* Add a new node to the tree, in the place determined by the empty PATH.
38 * It's the caller's responsibility to ensure that inserting the node here
39 * respects any ordering invariants.
41 * The new node is not copied, and its storage must remain valid until the
42 * node is removed or the tree is discarded.
44 * Returns `XYLA_RC_OK'.
47 struct xyla_splay_node *left, *right;
48 xyla_bt_updfn *updfn = cls ? cls->ops->upd : 0;
51 /* Set up the node's links. */
52 node->bt.left = node->bt.right = 0; node->spl.parent = 0;
54 /* If the tree isn't empty then hook the node onto the appropriate null
59 /* Find the actual null link, if the path is out of date. */
60 XYLA__ASSERT(path->f); side = xyla__splay_resolve_path(path);
63 xyla__splay_split(cls, &node->bt.left, &node->bt.right,
66 /* Attach the left and right subtrees. */
67 left = SPLAY_NODE(node->bt.left); if (left) left->spl.parent = node;
68 right = SPLAY_NODE(node->bt.right); if (right) right->spl.parent = node;
71 /* Update the new root node. */
72 if (updfn) updfn(cls, &node->bt);
74 /* Set it as the root and return. */
75 *path->root = &node->bt;
79 int xyla_splay_remove(struct xyla_bt_nodecls *cls,
80 struct xyla_splay_path *path)
82 /* Remove the node identified by the PATH. The node was allocated by the
83 * caller, and should be freed by the caller in whatever way is
86 * Returns `XYLA_RC_OK'.
89 struct xyla_splay_node *node, *parent;
90 struct xyla_bt_node **link;
91 xyla_bt_updfn *updfn = cls ? cls->ops->upd : 0;
94 node = path->node; XYLA__ASSERT(node); XYLA__ASSERT(!path->f);
96 /* Replace the node by the result of joining its children. */
97 parent = node->spl.parent;
98 if (!parent) link = path->root;
99 else if (parent->bt.left == &node->bt) link = &parent->bt.left;
100 else link = &parent->bt.right;
101 node = xyla__splay_join(cls,
102 SPLAY_NODE(node->bt.left),
103 SPLAY_NODE(node->bt.right));
104 *link = node ? &node->bt : 0; if (node) node->spl.parent = parent;
106 /* Finally, xyla_splay at the parent node, if there is one. */
108 xyla__splay_splay(cls, parent); *path->root = &parent->bt;
109 if (updfn) updfn(cls, &parent->bt);
116 /*----- That's all, folks -------------------------------------------------*/