tupperware: avl: add range mapping function
This commit is contained in:
parent
9e0706a7f3
commit
123ae1a347
|
@ -60,5 +60,7 @@ void avl_merge_all(struct avl *tree, struct avl *more);
|
|||
void avl_prefix_map(struct avl *tree, avl_map_f map, void *cookie);
|
||||
void avl_infix_map(struct avl *tree, avl_map_f map, void *cookie);
|
||||
void avl_postfix_map(struct avl *tree, avl_map_f map, void *cookie);
|
||||
void avl_map_between(const struct avl *tree,
|
||||
struct avl_node *inter[2], avl_map_f map, void *cookie);
|
||||
|
||||
#endif /* !TUPPERWARE_AVL_H */
|
||||
|
|
62
src/avl.c
62
src/avl.c
|
@ -522,3 +522,65 @@ struct between_parameters {
|
|||
avl_map_f map;
|
||||
void *cookie;
|
||||
};
|
||||
|
||||
static bool map_between_helper(struct avl_node *cur,
|
||||
const struct avl_node *end, avl_map_f map, void *cookie) {
|
||||
if (!cur)
|
||||
return false;
|
||||
if (cur == end)
|
||||
return true;
|
||||
if (map_between_helper(cur->left, end, map, cookie))
|
||||
return true;
|
||||
map(cur, cookie);
|
||||
return map_between_helper(cur->right, end, map, cookie);
|
||||
}
|
||||
|
||||
static bool map_between_right(struct avl_node *cur,
|
||||
const struct avl_node *end, avl_map_f map, void *cookie) {
|
||||
if (!cur)
|
||||
return false;
|
||||
if (cur == end)
|
||||
return true;
|
||||
map(cur, cookie);
|
||||
return map_between_helper(cur->right, end, map, cookie);
|
||||
}
|
||||
|
||||
static struct avl_node *find_parent(const struct avl *tree,
|
||||
struct avl_node *cur, const struct avl_node *v) {
|
||||
struct avl_node *parent = NULL;
|
||||
|
||||
int c = 0;
|
||||
while (cur && (c = tree->cmp(v, cur, tree->cookie))) {
|
||||
parent = cur;
|
||||
if (c < 0)
|
||||
cur = cur->left;
|
||||
else
|
||||
cur = cur->right;
|
||||
}
|
||||
|
||||
if (!cur)
|
||||
return NULL;
|
||||
if (cur == v)
|
||||
return parent;
|
||||
if (cur->left == v || cur->right == v)
|
||||
return cur; // NOTE: needs better handling
|
||||
if ((parent = find_parent(tree, cur->right, v)))
|
||||
return parent;
|
||||
if ((parent = find_parent(tree, cur->left, v)))
|
||||
return parent;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void avl_map_between(const struct avl *tree,
|
||||
struct avl_node *inter[2], avl_map_f map, void *cookie) {
|
||||
if (!tree || !tree->root)
|
||||
return;
|
||||
|
||||
struct avl_node *begin = inter[0];
|
||||
const struct avl_node *end = inter[1];
|
||||
// FIXME: finding the parent is inefficient
|
||||
while (begin && !map_between_right(begin, end, map, cookie)) {
|
||||
begin = find_parent(tree, tree->root, begin);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue