feat(tree): add tree iterator
This commit is contained in:
parent
ef5037f941
commit
a6ed89d8cd
7 changed files with 123 additions and 10 deletions
|
|
@ -1,11 +1,5 @@
|
|||
#include "vieter_tree_internal.h"
|
||||
#include "vieter_tree_node.h"
|
||||
#include "vieter_tree_balancing.h"
|
||||
|
||||
struct vieter_tree {
|
||||
uint64_t size;
|
||||
vieter_tree_node *root;
|
||||
};
|
||||
#include "vieter_tree_internal.h"
|
||||
|
||||
vieter_tree *vieter_tree_init() { return calloc(1, sizeof(vieter_tree)); }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,22 @@
|
|||
#include "vieter_tree.h"
|
||||
#include "vieter_tree_node.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct vieter_tree {
|
||||
uint64_t size;
|
||||
vieter_tree_node *root;
|
||||
};
|
||||
|
||||
/*
|
||||
* Inspect whether the tree is still a valid red-black-tree.
|
||||
*
|
||||
* @return true if valid, false otherwise.
|
||||
*/
|
||||
bool vieter_tree_validate(vieter_tree *tree);
|
||||
|
||||
struct vieter_tree_iterator {
|
||||
vieter_tree_node *current_node;
|
||||
bool started;
|
||||
bool done;
|
||||
};
|
||||
|
|
|
|||
49
src/tree/vieter_tree_iterator.c
Normal file
49
src/tree/vieter_tree_iterator.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include "vieter_tree.h"
|
||||
#include "vieter_tree_internal.h"
|
||||
|
||||
vieter_tree_iterator *vieter_tree_iterator_from(vieter_tree *tree) {
|
||||
vieter_tree_iterator *iter = calloc(1, sizeof(vieter_tree_iterator));
|
||||
|
||||
// An empty tree's iterator will be done immediately
|
||||
if (tree->size == 0) {
|
||||
iter->started = true;
|
||||
iter->done = true;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
iter->current_node = tree->root;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
vieter_tree_error vieter_tree_iterator_next(void **out,
|
||||
vieter_tree_iterator *iter) {
|
||||
if (iter->done) {
|
||||
return vieter_tree_iterator_done;
|
||||
}
|
||||
|
||||
if (!iter->started) {
|
||||
while (iter->current_node->children[0] != NULL) {
|
||||
iter->current_node = iter->current_node->children[0];
|
||||
}
|
||||
|
||||
iter->started = true;
|
||||
}
|
||||
|
||||
*out = iter->current_node->data;
|
||||
|
||||
iter->current_node = vieter_tree_node_next(iter->current_node);
|
||||
|
||||
if (iter->current_node == NULL) {
|
||||
iter->done = true;
|
||||
}
|
||||
|
||||
return vieter_tree_ok;
|
||||
}
|
||||
|
||||
void vieter_tree_iterator_free(vieter_tree_iterator **ptp) {
|
||||
free(*ptp);
|
||||
|
||||
*ptp = NULL;
|
||||
}
|
||||
|
|
@ -150,3 +150,22 @@ void vieter_tree_node_set(vieter_tree_node *node, vieter_tree_node_flag flag,
|
|||
bool vieter_tree_node_get(vieter_tree_node *node, vieter_tree_node_flag flag) {
|
||||
return (node->flags & flag) != 0;
|
||||
}
|
||||
|
||||
vieter_tree_node *vieter_tree_node_next(vieter_tree_node *node) {
|
||||
if (node->children[1] != NULL) {
|
||||
node = node->children[1];
|
||||
|
||||
while (node->children[0] != NULL) {
|
||||
node = node->children[0];
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
while (node->parent != NULL &&
|
||||
vieter_tree_node_get(node, vieter_tree_node_right)) {
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
return node->parent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,4 +77,10 @@ void vieter_tree_node_set_children(vieter_tree_node *parent, vieter_tree_node **
|
|||
*/
|
||||
void vieter_tree_node_set_child(vieter_tree_node *parent, vieter_tree_node *child, bool right);
|
||||
|
||||
/*
|
||||
* Return the in-order successor of the given node, or NULL if it's the last
|
||||
* node in the tree.
|
||||
*/
|
||||
vieter_tree_node *vieter_tree_node_next(vieter_tree_node *node);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Reference in a new issue