meta: rename to fx
This commit is contained in:
440
core/btree.c
440
core/btree.c
@@ -50,45 +50,45 @@
|
||||
|
||||
this file intentionally excludes any kind of search function implementation.
|
||||
it is up to the programmer to implement their own tree node type
|
||||
using b_btree_node, and their own search function using b_btree.
|
||||
using fx_bst_node, and their own search function using fx_bst.
|
||||
this allows the programmer to define their own node types with complex
|
||||
non-integer key types. btree.h contains a number of macros to help
|
||||
define these functions. the macros do all the work, you just have to
|
||||
provide a comparator function.
|
||||
*/
|
||||
|
||||
#include <blue/core/btree.h>
|
||||
#include <fx/core/btree.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define IS_LEFT_CHILD(p, c) ((p) && (c) && ((p)->b_left == (c)))
|
||||
#define IS_RIGHT_CHILD(p, c) ((p) && (c) && ((p)->b_right == (c)))
|
||||
#define IS_LEFT_CHILD(p, c) ((p) && (c) && ((p)->n_left == (c)))
|
||||
#define IS_RIGHT_CHILD(p, c) ((p) && (c) && ((p)->n_right == (c)))
|
||||
|
||||
#define HAS_LEFT_CHILD(x) ((x) && ((x)->b_left))
|
||||
#define HAS_RIGHT_CHILD(x) ((x) && ((x)->b_right))
|
||||
#define HAS_LEFT_CHILD(x) ((x) && ((x)->n_left))
|
||||
#define HAS_RIGHT_CHILD(x) ((x) && ((x)->n_right))
|
||||
|
||||
#define HAS_NO_CHILDREN(x) ((x) && (!(x)->b_left) && (!(x)->b_right))
|
||||
#define HAS_NO_CHILDREN(x) ((x) && (!(x)->n_left) && (!(x)->n_right))
|
||||
#define HAS_ONE_CHILD(x) \
|
||||
((HAS_LEFT_CHILD(x) && !HAS_RIGHT_CHILD(x)) \
|
||||
|| (!HAS_LEFT_CHILD(x) && HAS_RIGHT_CHILD(x)))
|
||||
#define HAS_TWO_CHILDREN(x) (HAS_LEFT_CHILD(x) && HAS_RIGHT_CHILD(x))
|
||||
|
||||
#define HEIGHT(x) ((x) ? (x)->b_height : 0)
|
||||
#define HEIGHT(x) ((x) ? (x)->n_height : 0)
|
||||
|
||||
struct b_btree_iterator_p {
|
||||
struct fx_bst_iterator_p {
|
||||
size_t i, depth;
|
||||
b_btree_node *node;
|
||||
b_btree *_b;
|
||||
fx_bst_node *node;
|
||||
fx_bst *_b;
|
||||
};
|
||||
|
||||
static inline void update_height(struct b_btree_node *x)
|
||||
static inline void update_height(struct fx_bst_node *x)
|
||||
{
|
||||
x->b_height = MAX(HEIGHT(x->b_left), HEIGHT((x->b_right))) + 1;
|
||||
x->n_height = MAX(HEIGHT(x->n_left), HEIGHT((x->n_right))) + 1;
|
||||
}
|
||||
|
||||
static inline int bf(struct b_btree_node *x)
|
||||
static inline int bf(struct fx_bst_node *x)
|
||||
{
|
||||
int bf = 0;
|
||||
|
||||
@@ -96,12 +96,12 @@ static inline int bf(struct b_btree_node *x)
|
||||
return bf;
|
||||
}
|
||||
|
||||
if (x->b_right) {
|
||||
bf += x->b_right->b_height;
|
||||
if (x->n_right) {
|
||||
bf += x->n_right->n_height;
|
||||
}
|
||||
|
||||
if (x->b_left) {
|
||||
bf -= x->b_left->b_height;
|
||||
if (x->n_left) {
|
||||
bf -= x->n_left->n_height;
|
||||
}
|
||||
|
||||
return bf;
|
||||
@@ -130,38 +130,38 @@ static inline int bf(struct b_btree_node *x)
|
||||
/ \
|
||||
. .
|
||||
|
||||
note that this function does NOT update b_height for the rotated
|
||||
note that this function does NOT update fx_height for the rotated
|
||||
nodes. it is up to you to call update_height_to_root().
|
||||
*/
|
||||
static void rotate_left(struct b_btree *tree, struct b_btree_node *x)
|
||||
static void rotate_left(struct fx_bst *tree, struct fx_bst_node *x)
|
||||
{
|
||||
struct b_btree_node *y = x->b_right;
|
||||
struct b_btree_node *p = x->b_parent;
|
||||
struct fx_bst_node *y = x->n_right;
|
||||
struct fx_bst_node *p = x->n_parent;
|
||||
|
||||
if (y->b_left) {
|
||||
y->b_left->b_parent = x;
|
||||
if (y->n_left) {
|
||||
y->n_left->n_parent = x;
|
||||
}
|
||||
|
||||
x->b_right = y->b_left;
|
||||
x->n_right = y->n_left;
|
||||
|
||||
if (!p) {
|
||||
tree->b_root = y;
|
||||
} else if (x == p->b_left) {
|
||||
p->b_left = y;
|
||||
tree->bst_root = y;
|
||||
} else if (x == p->n_left) {
|
||||
p->n_left = y;
|
||||
} else {
|
||||
p->b_right = y;
|
||||
p->n_right = y;
|
||||
}
|
||||
|
||||
x->b_parent = y;
|
||||
y->b_left = x;
|
||||
y->b_parent = p;
|
||||
x->n_parent = y;
|
||||
y->n_left = x;
|
||||
y->n_parent = p;
|
||||
}
|
||||
|
||||
static void update_height_to_root(struct b_btree_node *x)
|
||||
static void update_height_to_root(struct fx_bst_node *x)
|
||||
{
|
||||
while (x) {
|
||||
update_height(x);
|
||||
x = x->b_parent;
|
||||
x = x->n_parent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,31 +188,31 @@ static void update_height_to_root(struct b_btree_node *x)
|
||||
/ \
|
||||
. .
|
||||
|
||||
note that this function does NOT update b_height for the rotated
|
||||
note that this function does NOT update fx_height for the rotated
|
||||
nodes. it is up to you to call update_height_to_root().
|
||||
*/
|
||||
static void rotate_right(struct b_btree *tree, struct b_btree_node *y)
|
||||
static void rotate_right(struct fx_bst *tree, struct fx_bst_node *y)
|
||||
{
|
||||
struct b_btree_node *x = y->b_left;
|
||||
struct b_btree_node *p = y->b_parent;
|
||||
struct fx_bst_node *x = y->n_left;
|
||||
struct fx_bst_node *p = y->n_parent;
|
||||
|
||||
if (x->b_right) {
|
||||
x->b_right->b_parent = y;
|
||||
if (x->n_right) {
|
||||
x->n_right->n_parent = y;
|
||||
}
|
||||
|
||||
y->b_left = x->b_right;
|
||||
y->n_left = x->n_right;
|
||||
|
||||
if (!p) {
|
||||
tree->b_root = x;
|
||||
} else if (y == p->b_left) {
|
||||
p->b_left = x;
|
||||
tree->bst_root = x;
|
||||
} else if (y == p->n_left) {
|
||||
p->n_left = x;
|
||||
} else {
|
||||
p->b_right = x;
|
||||
p->n_right = x;
|
||||
}
|
||||
|
||||
y->b_parent = x;
|
||||
x->b_right = y;
|
||||
x->b_parent = p;
|
||||
y->n_parent = x;
|
||||
x->n_right = y;
|
||||
x->n_parent = p;
|
||||
}
|
||||
|
||||
/* for a given node Z, perform a right rotation on Z's right child,
|
||||
@@ -239,13 +239,13 @@ static void rotate_right(struct b_btree *tree, struct b_btree_node *y)
|
||||
. . . .
|
||||
|
||||
note that, unlike rotate_left and rotate_right, this function
|
||||
DOES update b_height for the rotated nodes (since it needs to be
|
||||
DOES update fx_height for the rotated nodes (since it needs to be
|
||||
done in a certain order).
|
||||
*/
|
||||
static void rotate_double_left(struct b_btree *tree, struct b_btree_node *z)
|
||||
static void rotate_double_left(struct fx_bst *tree, struct fx_bst_node *z)
|
||||
{
|
||||
struct b_btree_node *x = z->b_right;
|
||||
struct b_btree_node *y = x->b_left;
|
||||
struct fx_bst_node *x = z->n_right;
|
||||
struct fx_bst_node *y = x->n_left;
|
||||
|
||||
rotate_right(tree, x);
|
||||
rotate_left(tree, z);
|
||||
@@ -255,7 +255,7 @@ static void rotate_double_left(struct b_btree *tree, struct b_btree_node *z)
|
||||
|
||||
while (y) {
|
||||
update_height(y);
|
||||
y = y->b_parent;
|
||||
y = y->n_parent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,13 +283,13 @@ static void rotate_double_left(struct b_btree *tree, struct b_btree_node *z)
|
||||
. . . .
|
||||
|
||||
note that, unlike rotate_left and rotate_right, this function
|
||||
DOES update b_height for the rotated nodes (since it needs to be
|
||||
DOES update fx_height for the rotated nodes (since it needs to be
|
||||
done in a certain order).
|
||||
*/
|
||||
static void rotate_double_right(struct b_btree *tree, struct b_btree_node *z)
|
||||
static void rotate_double_right(struct fx_bst *tree, struct fx_bst_node *z)
|
||||
{
|
||||
struct b_btree_node *x = z->b_left;
|
||||
struct b_btree_node *y = x->b_right;
|
||||
struct fx_bst_node *x = z->n_left;
|
||||
struct fx_bst_node *y = x->n_right;
|
||||
|
||||
rotate_left(tree, x);
|
||||
rotate_right(tree, z);
|
||||
@@ -299,7 +299,7 @@ static void rotate_double_right(struct b_btree *tree, struct b_btree_node *z)
|
||||
|
||||
while (y) {
|
||||
update_height(y);
|
||||
y = y->b_parent;
|
||||
y = y->n_parent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,13 +311,13 @@ static void rotate_double_right(struct b_btree *tree, struct b_btree_node *z)
|
||||
is inserted into the tree.
|
||||
|
||||
this function depends on all nodes in the tree having
|
||||
correct b_height values.
|
||||
correct fx_height values.
|
||||
|
||||
@param w the node that was just inserted into the tree
|
||||
*/
|
||||
static void insert_fixup(struct b_btree *tree, struct b_btree_node *w)
|
||||
static void insert_fixup(struct fx_bst *tree, struct fx_bst_node *w)
|
||||
{
|
||||
struct b_btree_node *z = NULL, *y = NULL, *x = NULL;
|
||||
struct fx_bst_node *z = NULL, *y = NULL, *x = NULL;
|
||||
|
||||
z = w;
|
||||
while (z) {
|
||||
@@ -344,7 +344,7 @@ static void insert_fixup(struct b_btree *tree, struct b_btree_node *w)
|
||||
next_ancestor:
|
||||
x = y;
|
||||
y = z;
|
||||
z = z->b_parent;
|
||||
z = z->n_parent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ static void insert_fixup(struct b_btree *tree, struct b_btree_node *w)
|
||||
to restore balance after a node is deleted.
|
||||
|
||||
this function depends on all nodes in the tree having
|
||||
correct b_height values.
|
||||
correct fx_height values.
|
||||
|
||||
@param w one of the following:
|
||||
- the parent of the node that was deleted if the node
|
||||
@@ -366,20 +366,20 @@ static void insert_fixup(struct b_btree *tree, struct b_btree_node *w)
|
||||
- the node that replaced the node that was deleted, if
|
||||
the node that was deleted had one child.
|
||||
*/
|
||||
static void delete_fixup(struct b_btree *tree, struct b_btree_node *w)
|
||||
static void delete_fixup(struct fx_bst *tree, struct fx_bst_node *w)
|
||||
{
|
||||
struct b_btree_node *z = w;
|
||||
struct fx_bst_node *z = w;
|
||||
|
||||
while (z) {
|
||||
if (bf(z) > 1) {
|
||||
if (bf(z->b_right) >= 0) {
|
||||
if (bf(z->n_right) >= 0) {
|
||||
rotate_left(tree, z);
|
||||
update_height_to_root(z);
|
||||
} else {
|
||||
rotate_double_left(tree, z);
|
||||
}
|
||||
} else if (bf(z) < -1) {
|
||||
if (bf(z->b_left) <= 0) {
|
||||
if (bf(z->n_left) <= 0) {
|
||||
rotate_right(tree, z);
|
||||
update_height_to_root(z);
|
||||
} else {
|
||||
@@ -387,23 +387,23 @@ static void delete_fixup(struct b_btree *tree, struct b_btree_node *w)
|
||||
}
|
||||
}
|
||||
|
||||
z = z->b_parent;
|
||||
z = z->n_parent;
|
||||
}
|
||||
}
|
||||
|
||||
/* updates b_height for all nodes between the inserted node and the root
|
||||
/* updates fx_height for all nodes between the inserted node and the root
|
||||
of the tree, and calls insert_fixup.
|
||||
|
||||
@param node the node that was just inserted into the tree.
|
||||
*/
|
||||
void b_btree_insert_fixup(struct b_btree *tree, struct b_btree_node *node)
|
||||
void fx_bst_insert_fixup(struct fx_bst *tree, struct fx_bst_node *node)
|
||||
{
|
||||
node->b_height = 0;
|
||||
node->n_height = 0;
|
||||
|
||||
struct b_btree_node *cur = node;
|
||||
struct fx_bst_node *cur = node;
|
||||
while (cur) {
|
||||
update_height(cur);
|
||||
cur = cur->b_parent;
|
||||
cur = cur->n_parent;
|
||||
}
|
||||
|
||||
insert_fixup(tree, node);
|
||||
@@ -414,28 +414,28 @@ void b_btree_insert_fixup(struct b_btree *tree, struct b_btree_node *node)
|
||||
this function assumes that `node` has no children, and therefore
|
||||
doesn't need to be replaced.
|
||||
|
||||
updates b_height for all nodes between `node` and the tree root.
|
||||
updates fx_height for all nodes between `node` and the tree root.
|
||||
|
||||
@param node the node to delete.
|
||||
*/
|
||||
static struct b_btree_node *remove_node_with_no_children(
|
||||
struct b_btree *tree, struct b_btree_node *node)
|
||||
static struct fx_bst_node *remove_node_with_no_children(
|
||||
struct fx_bst *tree, struct fx_bst_node *node)
|
||||
{
|
||||
struct b_btree_node *w = node->b_parent;
|
||||
struct b_btree_node *p = node->b_parent;
|
||||
node->b_parent = NULL;
|
||||
struct fx_bst_node *w = node->n_parent;
|
||||
struct fx_bst_node *p = node->n_parent;
|
||||
node->n_parent = NULL;
|
||||
|
||||
if (!p) {
|
||||
tree->b_root = NULL;
|
||||
tree->bst_root = NULL;
|
||||
} else if (IS_LEFT_CHILD(p, node)) {
|
||||
p->b_left = NULL;
|
||||
p->n_left = NULL;
|
||||
} else {
|
||||
p->b_right = NULL;
|
||||
p->n_right = NULL;
|
||||
}
|
||||
|
||||
while (p) {
|
||||
update_height(p);
|
||||
p = p->b_parent;
|
||||
p = p->n_parent;
|
||||
}
|
||||
|
||||
return w;
|
||||
@@ -446,40 +446,40 @@ static struct b_btree_node *remove_node_with_no_children(
|
||||
this function assumes that `node` has one child.
|
||||
the child of `node` is inherited by `node`'s parent, and `node` is removed.
|
||||
|
||||
updates b_height for all nodes between the node that replaced
|
||||
updates fx_height for all nodes between the node that replaced
|
||||
`node` and the tree root.
|
||||
|
||||
@param node the node to delete.
|
||||
*/
|
||||
static struct b_btree_node *replace_node_with_one_subtree(
|
||||
struct b_btree *tree, struct b_btree_node *node)
|
||||
static struct fx_bst_node *replace_node_with_one_subtree(
|
||||
struct fx_bst *tree, struct fx_bst_node *node)
|
||||
{
|
||||
struct b_btree_node *p = node->b_parent;
|
||||
struct b_btree_node *z = NULL;
|
||||
struct fx_bst_node *p = node->n_parent;
|
||||
struct fx_bst_node *z = NULL;
|
||||
|
||||
if (HAS_LEFT_CHILD(node)) {
|
||||
z = node->b_left;
|
||||
z = node->n_left;
|
||||
} else {
|
||||
z = node->b_right;
|
||||
z = node->n_right;
|
||||
}
|
||||
|
||||
struct b_btree_node *w = z;
|
||||
struct fx_bst_node *w = z;
|
||||
if (!p) {
|
||||
tree->b_root = z;
|
||||
tree->bst_root = z;
|
||||
} else if (IS_LEFT_CHILD(p, node)) {
|
||||
p->b_left = z;
|
||||
p->n_left = z;
|
||||
} else if (IS_RIGHT_CHILD(p, node)) {
|
||||
p->b_right = z;
|
||||
p->n_right = z;
|
||||
}
|
||||
|
||||
z->b_parent = p;
|
||||
z->n_parent = p;
|
||||
|
||||
node->b_parent = NULL;
|
||||
node->b_left = node->b_right = NULL;
|
||||
node->n_parent = NULL;
|
||||
node->n_left = node->n_right = NULL;
|
||||
|
||||
while (z) {
|
||||
update_height(z);
|
||||
z = z->b_parent;
|
||||
z = z->n_parent;
|
||||
}
|
||||
|
||||
return w;
|
||||
@@ -495,79 +495,79 @@ static struct b_btree_node *replace_node_with_one_subtree(
|
||||
if Y has a child (it will never have more than one), have Y's parent inherit
|
||||
Y's child.
|
||||
|
||||
updates b_height for all nodes between the deepest node that was modified
|
||||
updates fx_height for all nodes between the deepest node that was modified
|
||||
and the tree root.
|
||||
|
||||
@param z the node to delete.
|
||||
*/
|
||||
static struct b_btree_node *replace_node_with_two_subtrees(
|
||||
struct b_btree *tree, struct b_btree_node *z)
|
||||
static struct fx_bst_node *replace_node_with_two_subtrees(
|
||||
struct fx_bst *tree, struct fx_bst_node *z)
|
||||
{
|
||||
/* x will replace z */
|
||||
struct b_btree_node *x = z->b_left;
|
||||
struct fx_bst_node *x = z->n_left;
|
||||
|
||||
while (x->b_right) {
|
||||
x = x->b_right;
|
||||
while (x->n_right) {
|
||||
x = x->n_right;
|
||||
}
|
||||
|
||||
/* y is the node that will replace x (if x has a left child) */
|
||||
struct b_btree_node *y = x->b_left;
|
||||
struct fx_bst_node *y = x->n_left;
|
||||
|
||||
/* w is the starting point for the height update and fixup */
|
||||
struct b_btree_node *w = x;
|
||||
if (w->b_parent != z) {
|
||||
w = w->b_parent;
|
||||
struct fx_bst_node *w = x;
|
||||
if (w->n_parent != z) {
|
||||
w = w->n_parent;
|
||||
}
|
||||
|
||||
if (y) {
|
||||
w = y;
|
||||
}
|
||||
|
||||
if (IS_LEFT_CHILD(x->b_parent, x)) {
|
||||
x->b_parent->b_left = y;
|
||||
} else if (IS_RIGHT_CHILD(x->b_parent, x)) {
|
||||
x->b_parent->b_right = y;
|
||||
if (IS_LEFT_CHILD(x->n_parent, x)) {
|
||||
x->n_parent->n_left = y;
|
||||
} else if (IS_RIGHT_CHILD(x->n_parent, x)) {
|
||||
x->n_parent->n_right = y;
|
||||
}
|
||||
|
||||
if (y) {
|
||||
y->b_parent = x->b_parent;
|
||||
y->n_parent = x->n_parent;
|
||||
}
|
||||
|
||||
if (IS_LEFT_CHILD(z->b_parent, z)) {
|
||||
z->b_parent->b_left = x;
|
||||
} else if (IS_RIGHT_CHILD(z->b_parent, z)) {
|
||||
z->b_parent->b_right = x;
|
||||
if (IS_LEFT_CHILD(z->n_parent, z)) {
|
||||
z->n_parent->n_left = x;
|
||||
} else if (IS_RIGHT_CHILD(z->n_parent, z)) {
|
||||
z->n_parent->n_right = x;
|
||||
}
|
||||
|
||||
x->b_parent = z->b_parent;
|
||||
x->b_left = z->b_left;
|
||||
x->b_right = z->b_right;
|
||||
x->n_parent = z->n_parent;
|
||||
x->n_left = z->n_left;
|
||||
x->n_right = z->n_right;
|
||||
|
||||
if (x->b_left) {
|
||||
x->b_left->b_parent = x;
|
||||
if (x->n_left) {
|
||||
x->n_left->n_parent = x;
|
||||
}
|
||||
|
||||
if (x->b_right) {
|
||||
x->b_right->b_parent = x;
|
||||
if (x->n_right) {
|
||||
x->n_right->n_parent = x;
|
||||
}
|
||||
|
||||
if (!x->b_parent) {
|
||||
tree->b_root = x;
|
||||
if (!x->n_parent) {
|
||||
tree->bst_root = x;
|
||||
}
|
||||
|
||||
struct b_btree_node *cur = w;
|
||||
struct fx_bst_node *cur = w;
|
||||
while (cur) {
|
||||
update_height(cur);
|
||||
cur = cur->b_parent;
|
||||
cur = cur->n_parent;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/* delete a node from the tree and re-balance it afterwards */
|
||||
void b_btree_delete(struct b_btree *tree, struct b_btree_node *node)
|
||||
void fx_bst_delete(struct fx_bst *tree, struct fx_bst_node *node)
|
||||
{
|
||||
struct b_btree_node *w = NULL;
|
||||
struct fx_bst_node *w = NULL;
|
||||
|
||||
if (HAS_NO_CHILDREN(node)) {
|
||||
w = remove_node_with_no_children(tree, node);
|
||||
@@ -581,14 +581,14 @@ void b_btree_delete(struct b_btree *tree, struct b_btree_node *node)
|
||||
delete_fixup(tree, w);
|
||||
}
|
||||
|
||||
node->b_left = node->b_right = node->b_parent = NULL;
|
||||
node->n_left = node->n_right = node->n_parent = NULL;
|
||||
}
|
||||
|
||||
static struct b_btree_node *first_node(const struct b_btree *tree, int *depth)
|
||||
static struct fx_bst_node *first_node(const struct fx_bst *tree, int *depth)
|
||||
{
|
||||
/* the first node in the tree is the node with the smallest key.
|
||||
we keep moving left until we can't go any further */
|
||||
struct b_btree_node *cur = tree->b_root;
|
||||
struct fx_bst_node *cur = tree->bst_root;
|
||||
int d = 0;
|
||||
|
||||
if (!cur) {
|
||||
@@ -596,47 +596,47 @@ static struct b_btree_node *first_node(const struct b_btree *tree, int *depth)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (cur->b_left) {
|
||||
while (cur->n_left) {
|
||||
d++;
|
||||
cur = cur->b_left;
|
||||
cur = cur->n_left;
|
||||
}
|
||||
|
||||
*depth = d;
|
||||
return cur;
|
||||
}
|
||||
|
||||
struct b_btree_node *b_btree_first(const struct b_btree *tree)
|
||||
struct fx_bst_node *fx_bst_first(const struct fx_bst *tree)
|
||||
{
|
||||
int d;
|
||||
return first_node(tree, &d);
|
||||
}
|
||||
|
||||
static struct b_btree_node *last_node(const struct b_btree *tree, int *depth)
|
||||
static struct fx_bst_node *last_node(const struct fx_bst *tree, int *depth)
|
||||
{
|
||||
/* the first node in the tree is the node with the largest key.
|
||||
we keep moving right until we can't go any further */
|
||||
struct b_btree_node *cur = tree->b_root;
|
||||
struct fx_bst_node *cur = tree->bst_root;
|
||||
int d = 0;
|
||||
if (!cur) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (cur->b_right) {
|
||||
while (cur->n_right) {
|
||||
d++;
|
||||
cur = cur->b_right;
|
||||
cur = cur->n_right;
|
||||
}
|
||||
|
||||
*depth = d;
|
||||
return cur;
|
||||
}
|
||||
|
||||
b_btree_node *b_btree_last(const struct b_btree *tree)
|
||||
fx_bst_node *fx_bst_last(const struct fx_bst *tree)
|
||||
{
|
||||
int d;
|
||||
return last_node(tree, &d);
|
||||
}
|
||||
|
||||
static b_btree_node *next_node(const struct b_btree_node *node, int *depth_diff)
|
||||
static fx_bst_node *next_node(const struct fx_bst_node *node, int *depth_diff)
|
||||
{
|
||||
if (!node) {
|
||||
return NULL;
|
||||
@@ -653,13 +653,13 @@ static b_btree_node *next_node(const struct b_btree_node *node, int *depth_diff)
|
||||
the sub-tree rooted at `node`. we need to go back to our parent
|
||||
and continue the search elsewhere.
|
||||
*/
|
||||
if (node->b_right) {
|
||||
if (node->n_right) {
|
||||
/* case 1: step into `node`'s right sub-tree and keep going
|
||||
left to find the smallest node */
|
||||
struct b_btree_node *cur = node->b_right;
|
||||
struct fx_bst_node *cur = node->n_right;
|
||||
depth++;
|
||||
while (cur->b_left) {
|
||||
cur = cur->b_left;
|
||||
while (cur->n_left) {
|
||||
cur = cur->n_left;
|
||||
depth++;
|
||||
}
|
||||
|
||||
@@ -671,16 +671,16 @@ static b_btree_node *next_node(const struct b_btree_node *node, int *depth_diff)
|
||||
if we encounter a step where we are our parent's left child,
|
||||
we've found a parent with a value larger than us. this parent
|
||||
is the in-order successor of `node` */
|
||||
while (node->b_parent && node->b_parent->b_left != node) {
|
||||
node = node->b_parent;
|
||||
while (node->n_parent && node->n_parent->n_left != node) {
|
||||
node = node->n_parent;
|
||||
depth--;
|
||||
}
|
||||
|
||||
*depth_diff = depth - 1;
|
||||
return node->b_parent;
|
||||
return node->n_parent;
|
||||
}
|
||||
|
||||
static b_btree_node *prev_node(const struct b_btree_node *node, int *depth_diff)
|
||||
static fx_bst_node *prev_node(const struct fx_bst_node *node, int *depth_diff)
|
||||
{
|
||||
if (!node) {
|
||||
return NULL;
|
||||
@@ -697,13 +697,13 @@ static b_btree_node *prev_node(const struct b_btree_node *node, int *depth_diff)
|
||||
the sub-tree rooted at `node`. we need to go back to our parent
|
||||
and continue the search elsewhere.
|
||||
*/
|
||||
if (node->b_left) {
|
||||
if (node->n_left) {
|
||||
/* case 1: step into `node`'s left sub-tree and keep going
|
||||
right to find the largest node */
|
||||
b_btree_node *cur = node->b_left;
|
||||
fx_bst_node *cur = node->n_left;
|
||||
depth++;
|
||||
while (cur->b_right) {
|
||||
cur = cur->b_right;
|
||||
while (cur->n_right) {
|
||||
cur = cur->n_right;
|
||||
depth++;
|
||||
}
|
||||
|
||||
@@ -715,65 +715,65 @@ static b_btree_node *prev_node(const struct b_btree_node *node, int *depth_diff)
|
||||
if we encounter a step where we are our parent's right child,
|
||||
we've found a parent with a value smaller than us. this parent
|
||||
is the in-order predecessor of `node`. */
|
||||
while (node->b_parent && node->b_parent->b_right != node) {
|
||||
node = node->b_parent;
|
||||
while (node->n_parent && node->n_parent->n_right != node) {
|
||||
node = node->n_parent;
|
||||
depth--;
|
||||
}
|
||||
|
||||
*depth_diff = depth - 1;
|
||||
return node->b_parent;
|
||||
return node->n_parent;
|
||||
}
|
||||
|
||||
b_btree_node *b_btree_next(const struct b_btree_node *node)
|
||||
fx_bst_node *fx_bst_next(const struct fx_bst_node *node)
|
||||
{
|
||||
int d;
|
||||
return next_node(node, &d);
|
||||
}
|
||||
|
||||
b_btree_node *b_btree_prev(const struct b_btree_node *node)
|
||||
fx_bst_node *fx_bst_prev(const struct fx_bst_node *node)
|
||||
{
|
||||
int d;
|
||||
return prev_node(node, &d);
|
||||
}
|
||||
|
||||
void b_btree_move(
|
||||
struct b_btree *tree, struct b_btree_node *dest, struct b_btree_node *src)
|
||||
void fx_bst_move(
|
||||
struct fx_bst *tree, struct fx_bst_node *dest, struct fx_bst_node *src)
|
||||
{
|
||||
if (src->b_parent) {
|
||||
if (src->b_parent->b_left == src) {
|
||||
src->b_parent->b_left = dest;
|
||||
if (src->n_parent) {
|
||||
if (src->n_parent->n_left == src) {
|
||||
src->n_parent->n_left = dest;
|
||||
} else {
|
||||
src->b_parent->b_right = dest;
|
||||
src->n_parent->n_right = dest;
|
||||
}
|
||||
}
|
||||
|
||||
if (src->b_left) {
|
||||
src->b_left->b_parent = dest;
|
||||
if (src->n_left) {
|
||||
src->n_left->n_parent = dest;
|
||||
}
|
||||
|
||||
if (src->b_right) {
|
||||
src->b_right->b_parent = dest;
|
||||
if (src->n_right) {
|
||||
src->n_right->n_parent = dest;
|
||||
}
|
||||
|
||||
if (tree->b_root == src) {
|
||||
tree->b_root = dest;
|
||||
if (tree->bst_root == src) {
|
||||
tree->bst_root = dest;
|
||||
}
|
||||
|
||||
memmove(dest, src, sizeof *src);
|
||||
}
|
||||
|
||||
b_iterator *b_btree_begin(struct b_btree *tree)
|
||||
fx_iterator *fx_bst_begin(struct fx_bst *tree)
|
||||
{
|
||||
b_iterator *it_obj = b_object_create(B_TYPE_BTREE_ITERATOR);
|
||||
fx_iterator *it_obj = fx_object_create(FX_TYPE_BTREE_ITERATOR);
|
||||
if (!it_obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct b_btree_iterator_p *it
|
||||
= b_object_get_private(it_obj, B_TYPE_BTREE_ITERATOR);
|
||||
struct fx_bst_iterator_p *it
|
||||
= fx_object_get_private(it_obj, FX_TYPE_BTREE_ITERATOR);
|
||||
int depth = 0;
|
||||
|
||||
it->_b = (struct b_btree *)tree;
|
||||
it->_b = (struct fx_bst *)tree;
|
||||
it->i = 0;
|
||||
it->node = first_node(tree, &depth);
|
||||
it->depth = depth;
|
||||
@@ -781,18 +781,18 @@ b_iterator *b_btree_begin(struct b_btree *tree)
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
const b_iterator *b_btree_cbegin(const struct b_btree *tree)
|
||||
const fx_iterator *fx_bst_cbegin(const struct fx_bst *tree)
|
||||
{
|
||||
b_iterator *it_obj = b_object_create(B_TYPE_BTREE_ITERATOR);
|
||||
fx_iterator *it_obj = fx_object_create(FX_TYPE_BTREE_ITERATOR);
|
||||
if (!it_obj) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct b_btree_iterator_p *it
|
||||
= b_object_get_private(it_obj, B_TYPE_BTREE_ITERATOR);
|
||||
struct fx_bst_iterator_p *it
|
||||
= fx_object_get_private(it_obj, FX_TYPE_BTREE_ITERATOR);
|
||||
int depth = 0;
|
||||
|
||||
it->_b = (struct b_btree *)tree;
|
||||
it->_b = (struct fx_bst *)tree;
|
||||
it->i = 0;
|
||||
it->node = first_node(tree, &depth);
|
||||
it->depth = depth;
|
||||
@@ -800,13 +800,13 @@ const b_iterator *b_btree_cbegin(const struct b_btree *tree)
|
||||
return it_obj;
|
||||
}
|
||||
|
||||
static enum b_status iterator_move_next(const b_iterator *obj)
|
||||
static enum fx_status iterator_move_next(const fx_iterator *obj)
|
||||
{
|
||||
struct b_btree_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_BTREE_ITERATOR);
|
||||
struct fx_bst_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_BTREE_ITERATOR);
|
||||
|
||||
int depth_diff = 0;
|
||||
struct b_btree_node *next = next_node(it->node, &depth_diff);
|
||||
struct fx_bst_node *next = next_node(it->node, &depth_diff);
|
||||
|
||||
if (!next) {
|
||||
it->node = NULL;
|
||||
@@ -821,19 +821,19 @@ static enum b_status iterator_move_next(const b_iterator *obj)
|
||||
return true;
|
||||
}
|
||||
|
||||
static enum b_status iterator_erase(b_iterator *obj)
|
||||
static enum fx_status iterator_erase(fx_iterator *obj)
|
||||
{
|
||||
struct b_btree_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_BTREE_ITERATOR);
|
||||
struct fx_bst_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_BTREE_ITERATOR);
|
||||
|
||||
if (!it->node) {
|
||||
return B_ERR_OUT_OF_BOUNDS;
|
||||
return FX_ERR_OUT_OF_BOUNDS;
|
||||
}
|
||||
|
||||
int depth_diff = 0;
|
||||
struct b_btree_node *next = next_node(it->node, &depth_diff);
|
||||
struct fx_bst_node *next = next_node(it->node, &depth_diff);
|
||||
|
||||
b_btree_delete(it->_b, it->node);
|
||||
fx_bst_delete(it->_b, it->node);
|
||||
if (!next) {
|
||||
it->node = NULL;
|
||||
it->depth = 0;
|
||||
@@ -841,51 +841,51 @@ static enum b_status iterator_erase(b_iterator *obj)
|
||||
it->node = next;
|
||||
it->depth = 0;
|
||||
|
||||
struct b_btree_node *cur = next->b_parent;
|
||||
struct fx_bst_node *cur = next->n_parent;
|
||||
while (cur) {
|
||||
it->depth++;
|
||||
cur = cur->b_parent;
|
||||
cur = cur->n_parent;
|
||||
}
|
||||
}
|
||||
|
||||
return B_SUCCESS;
|
||||
return FX_SUCCESS;
|
||||
}
|
||||
|
||||
static b_iterator_value iterator_get_value(b_iterator *obj)
|
||||
static fx_iterator_value iterator_get_value(fx_iterator *obj)
|
||||
{
|
||||
struct b_btree_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_BTREE_ITERATOR);
|
||||
struct fx_bst_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_BTREE_ITERATOR);
|
||||
|
||||
return B_ITERATOR_VALUE_PTR(it->node);
|
||||
return FX_ITERATOR_VALUE_PTR(it->node);
|
||||
}
|
||||
|
||||
static const b_iterator_value iterator_get_cvalue(const b_iterator *obj)
|
||||
static const fx_iterator_value iterator_get_cvalue(const fx_iterator *obj)
|
||||
{
|
||||
struct b_btree_iterator_p *it
|
||||
= b_object_get_private(obj, B_TYPE_BTREE_ITERATOR);
|
||||
struct fx_bst_iterator_p *it
|
||||
= fx_object_get_private(obj, FX_TYPE_BTREE_ITERATOR);
|
||||
|
||||
return B_ITERATOR_VALUE_CPTR(it->node);
|
||||
return FX_ITERATOR_VALUE_CPTR(it->node);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
// ---- b_btree_iterator DEFINITION
|
||||
B_TYPE_CLASS_DEFINITION_BEGIN(b_btree_iterator)
|
||||
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
|
||||
B_INTERFACE_ENTRY(to_string) = NULL;
|
||||
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
|
||||
// ---- fx_bst_iterator DEFINITION
|
||||
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_bst_iterator)
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
|
||||
B_TYPE_CLASS_INTERFACE_BEGIN(b_iterator, B_TYPE_ITERATOR)
|
||||
B_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
|
||||
B_INTERFACE_ENTRY(it_erase) = iterator_erase;
|
||||
B_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
|
||||
B_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
|
||||
B_TYPE_CLASS_INTERFACE_END(b_iterator, B_TYPE_ITERATOR)
|
||||
B_TYPE_CLASS_DEFINITION_END(b_btree_iterator)
|
||||
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_iterator, FX_TYPE_ITERATOR)
|
||||
FX_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
|
||||
FX_INTERFACE_ENTRY(it_erase) = iterator_erase;
|
||||
FX_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
|
||||
FX_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
|
||||
FX_TYPE_CLASS_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR)
|
||||
FX_TYPE_CLASS_DEFINITION_END(fx_bst_iterator)
|
||||
|
||||
B_TYPE_DEFINITION_BEGIN(b_btree_iterator)
|
||||
B_TYPE_ID(0x432779d7, 0xc03a, 0x48ea, 0xae8f, 0x12c666c767ae);
|
||||
B_TYPE_EXTENDS(B_TYPE_ITERATOR);
|
||||
B_TYPE_CLASS(b_btree_iterator_class);
|
||||
B_TYPE_INSTANCE_PRIVATE(struct b_btree_iterator_p);
|
||||
B_TYPE_DEFINITION_END(b_btree_iterator)
|
||||
FX_TYPE_DEFINITION_BEGIN(fx_bst_iterator)
|
||||
FX_TYPE_ID(0x432779d7, 0xc03a, 0x48ea, 0xae8f, 0x12c666c767ae);
|
||||
FX_TYPE_EXTENDS(FX_TYPE_ITERATOR);
|
||||
FX_TYPE_CLASS(fx_bst_iterator_class);
|
||||
FX_TYPE_INSTANCE_PRIVATE(struct fx_bst_iterator_p);
|
||||
FX_TYPE_DEFINITION_END(fx_bst_iterator)
|
||||
|
||||
Reference in New Issue
Block a user