3 * Path utilities for treaps
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 void *xyla_treap_current(const struct xyla_treap_path *path)
35 /* Return the node currently designated by PATH, or null if PATH is
39 return (XYLA_BT_CURRENT(path->p, path->k));
42 void xyla_treap_copypath(struct xyla_treap_path *newpath,
43 const struct xyla_treap_path *path)
45 /* Make a copy of PATH as NEWPATH. This has the same effect as simply
46 * assigning the path structures, but may be significantly faster because
47 * it only copies the active part of the path vector.
52 XYLA_BT_COPYPATH(newpath->p, path->p, k);
56 void *xyla_treap_firstpath(struct xyla_bt_node **root,
57 struct xyla_treap_path *path)
59 /* Return the first node in the tree, together with a PATH to the requested
60 * node, which can be used to remove them, or to navigate to other nodes in
61 * the tree. Return null if the tree is empty.
64 struct xyla_bt_node *node;
67 XYLA_BT_EXTRMPATH(rc, node, root, path->p, path->k,
68 left, XYLA_TREAP_HTMAX);
69 if (rc) xyla__treap_boundfail();
73 void *xyla_treap_lastpath(struct xyla_bt_node **root,
74 struct xyla_treap_path *path)
76 /* Return the last node in the tree, together with a PATH to the requested
77 * node, which can be used to remove them, or to navigate to other nodes in
78 * the tree. Return null if the tree is empty.
81 struct xyla_bt_node *node;
84 XYLA_BT_EXTRMPATH(rc, node, root, path->p, path->k,
85 right, XYLA_TREAP_HTMAX);
86 if (rc) xyla__treap_boundfail();
90 void *xyla_treap_nextpath(struct xyla_treap_path *path)
92 /* Return the next node in the tree, and update the PATH to the requested
93 * node, which can be used to remove them, or to navigate to other nodes in
96 * If the path is full, i.e., refers to an existing node, then the function
97 * returns that node's successor. If the path is empty, i.e., refers to a
98 * space between nodes where a new node can be inserted, then the function
99 * returns the node at the upper end of the gap, unless the `gap' is
100 * actually at the extreme right of the tree and no such node exists. In
101 * the latter case, a null pointer is returned. The path is modified to
102 * refer to the new node, if any, or to the gap at the extreme right of the
106 struct xyla_bt_node *node;
109 XYLA_BT_STEPPATH(rc, node, path->p, path->k,
110 right, left, XYLA_TREAP_HTMAX);
111 if (rc) xyla__treap_boundfail();
115 void *xyla_treap_prevpath(struct xyla_treap_path *path)
117 /* Return the previous node in the tree, and update the PATH to the
118 * requested node, which can be used to remove them, or to navigate to
119 * other nodes in the tree.
121 * If the path is full, i.e., refers to an existing node, then the function
122 * returns that node's predecessor. If the path is empty, i.e., refers to
123 * a space between nodes where a new node can be inserted, then the
124 * function returns the node at the lower end of the gap, unless the `gap'
125 * is actually at the extreme left of the tree and no such node exists. In
126 * the latter case, a null pointer is returned. The path is modified to
127 * refer to the new node, if any, or to the gap at the extreme left of the
131 struct xyla_bt_node *node;
134 XYLA_BT_STEPPATH(rc, node, path->p, path->k,
135 left, right, XYLA_TREAP_HTMAX);
136 if (rc) xyla__treap_boundfail();
140 void xyla_treap_beforepath(struct xyla_treap_path *path)
142 /* Advance the PATH to just before the current node. The path thereby
143 * becomes empty, suitable to insert an element or split the tree just
144 * before the previously selected node.
149 XYLA_BT_NUDGEPATH(rc, path->p, path->k, left, right, XYLA_TREAP_HTMAX);
150 if (rc) xyla__treap_boundfail();
153 void xyla_treap_afterpath(struct xyla_treap_path *path)
155 /* Advance the PATH to just after the current node. The path thereby
156 * becomes empty, suitable to insert an element or split the tree just
157 * after the previously selected node.
162 XYLA_BT_NUDGEPATH(rc, path->p, path->k, right, left, XYLA_TREAP_HTMAX);
163 if (rc) xyla__treap_boundfail();
166 void *xyla_treap_rootpath(struct xyla_bt_node **root,
167 struct xyla_treap_path *path)
169 /* Initialize PATH to refer to the tree root, given the address ROOT of the
170 * root link, and return this root node. The resulting path will be empty
171 * if and only if the tree is empty.
174 struct xyla_bt_node *node;
176 XYLA_BT_ROOTPATH(node, root, path->p, path->k);
180 void *xyla_treap_uppath(unsigned *pos_out, struct xyla_treap_path *path)
182 /* Update the PATH to refer to the parent of the link currently designated;
183 * return this parent node, and set *POS_OUT to the `XYLA_BTPOS_...'
184 * constant describing the link's relation to the parent. If the path
185 * initially designated the tree's root link, then return null, set
186 * *POS_OUT to `XYLA_BTPOS_ROOT', and leave the path unchanged; otherwise,
187 * the tree becomes full.
190 struct xyla_bt_node *node;
192 XYLA_BT_PARENTPATH(node, *pos_out, path->p, path->k);
196 void *xyla_treap_leftpath(struct xyla_treap_path *path)
198 /* Update the PATH to refer to the left child of the node currently
199 * designated, and set NODE to be this child node. The PATH must initially
200 * have been full, and may become empty as a result.
203 struct xyla_bt_node *node;
206 XYLA_BT_CHILDPATH(rc, node, path->p, path->k, left, XYLA_TREAP_HTMAX);
207 if (rc) xyla__treap_boundfail();
211 void *xyla_treap_rightpath(struct xyla_treap_path *path)
213 /* Update the PATH to refer to the right child of the node currently
214 * designated, and set NODE to be this child node. The PATH must initially
215 * have been full, and may become empty as a result.
218 struct xyla_bt_node *node;
221 XYLA_BT_CHILDPATH(rc, node, path->p, path->k, right, XYLA_TREAP_HTMAX);
222 if (rc) xyla__treap_boundfail();
226 void xyla_treap_replace(const struct xyla_treap_path *path,
227 struct xyla_treap_node *node)
229 /* Replace the node identified by the PATH with the given NODE. The node's
230 * links need not be initialized. The replacement node's weight is copied
231 * from the original. Paths and iterators are not invalidated. It is the
232 * caller's responsibility to ensure that any ordering invariants are
233 * respected as a result of the change.
236 struct xyla_treap_node *old_node;
239 old_node = TREAP_NODE(*path->p[k]); XYLA__ASSERT(old_node);
240 node->bt = old_node->bt; node->trp.wt = old_node->trp.wt;
243 void xyla_treap_ripple(struct xyla_bt_nodecls *cls,
244 const struct xyla_treap_path *path)
246 /* Update a node's ancestors -- i.e., call the node class `upd' function on
247 * them, in ascending order -- after it has been modified. The PATH
248 * describes a full path to the node that has been changed. The PATH
252 XYLA_BT_RIPPLE(cls, path->p, path->k);
255 int xyla_treap_ascend(xyla_bt_ascendfn *fn,
256 const struct xyla_treap_path *path, void *arg)
258 /* Ascend the tree along the PATH, allowing FN to accumulate summary data
259 * from the nodes to the root; see `XYLA_BT_ASCEND' for details. If FN
260 * returns nonzero, then stop and return the nonzero value; otherwise
261 * return zero. The PATH remains valid.
266 XYLA_BT_ASCEND(rc, fn, path->p, path->k, arg);
270 /*----- That's all, folks -------------------------------------------------*/