3 * Iteration 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 /* Iteration doesn't work like the other trees in this library, because we
34 * have parent pointers. Instead, the `iterator' simply keeps track of the
35 * /next/ node to return.
38 #define INITITER(root, it, back) do { \
39 const struct xyla_splay_node *_next = CONST_SPLAY_NODE(root), *_nnext; \
41 /* Initialize the `next' node to the backmost node in the tree. */ \
45 (it)->top = _next->spl.parent; \
47 _nnext = CONST_SPLAY_NODE(_next->bt.back); if (!_nnext) break; \
54 #define NEXT(node, it, fwd, back) do { \
55 const struct xyla_splay_node *_node, *_next, *_nnext, *_old; \
57 /* The next node to return is just the one recorded in the \
62 /* Now advance the iterator to the /next/ node. There are two cases \
66 _next = CONST_SPLAY_NODE(_node->bt.fwd); \
68 /* The node's forward subtree is non-empty. The next node is the \
69 * backmode node in the forward subtree. \
73 _nnext = CONST_SPLAY_NODE(_next->bt.back); \
78 /* The forward subtree is empty. The next node is the most \
79 * recent ancestor that we descend from through a backward link. \
80 * If there is no such ancestor then the iteration concludes \
85 do { _old = _next; _next = _old->spl.parent; } \
86 while (_next != (it)->top && &_old->bt == _next->bt.fwd); \
93 void xyla_splay_inititer(const struct xyla_bt_node *root,
94 struct xyla_splay_iter *it)
96 /* Initialize the iterator IT to start returning nodes in right-to-left
97 * order from the tree rooted at ROOT.
100 INITITER(root, it, left);
103 void *xyla_splay_next(struct xyla_splay_iter *it)
105 /* Advances a tree iterator. Inserting or removing elements does /not/
106 * invalidate the iterator. It is permitted to free all of the nodes by
107 * iterating over the tree in the obvious manner:
109 * xyla_splay_inititer(tree, &it);
111 * node = xyla_splay_next(&it); if (!node) break;
115 * It's probably better to use `xyla_bt_severfirst' for this task.
118 const struct xyla_splay_node *node;
119 NEXT(node, it, right, left); return (UNCONST(void, node));
122 void xyla_splay_initriter(const struct xyla_bt_node *root,
123 struct xyla_splay_riter *rit)
125 /* Initialize the iterator RIT to start returning nodes in left-to-right
126 * order from the tree rooted at ROOT.
129 INITITER(root, rit, right);
132 void *xyla_splay_prev(struct xyla_splay_riter *rit)
134 /* Advances a tree iterator. Inserting or removing elements does /not/
135 * invalidate the iterator. It is permitted to free all of the nodes by
136 * iterating over the tree in the obvious manner:
138 * xyla_splay_inititer(tree, &rit);
140 * node = xyla_splay_next(&rit); if (!node) break;
144 * It's probably better to use `xyla_bt_severfirst' for this task.
147 const struct xyla_splay_node *node;
148 NEXT(node, rit, left, right); return (UNCONST(void, node));
151 /*----- That's all, folks -------------------------------------------------*/