📄 btree.c
字号:
/*
* FILE: btree.c
* PROGRAM: RAT
* AUTHOR: O.Hodson
* MODIFIED: C.Perkins
*
* Binary tree implementation - Mostly verbatim from:
*
* Introduction to Algorithms by Corman, Leisserson, and Rivest,
* MIT Press / McGraw Hill, 1990.
*
*/
#include "config_unix.h"
#include "config_win32.h"
#include "debug.h"
#include "memory.h"
#include "btree.h"
typedef struct s_btree_node {
uint32_t key;
void *data;
struct s_btree_node *parent;
struct s_btree_node *left;
struct s_btree_node *right;
uint32_t magic;
} btree_node_t;
struct s_btree {
btree_node_t *root;
uint32_t magic;
int count;
};
/*****************************************************************************/
/* Debugging functions... */
/*****************************************************************************/
#define BTREE_MAGIC 0x10101010
#define BTREE_NODE_MAGIC 0x01010101
static int btree_count;
static void
btree_validate_node(btree_node_t *node, btree_node_t *parent)
{
ASSERT(node->magic == BTREE_NODE_MAGIC);
ASSERT(node->parent == parent);
btree_count++;
if (node->left != NULL) {
btree_validate_node(node->left, node);
}
if (node->right != NULL) {
btree_validate_node(node->right, node);
}
}
static void
btree_validate(btree_t *t)
{
ASSERT(t->magic == BTREE_MAGIC);
#ifdef DEBUG
btree_count = 0;
if (t->root != NULL) {
btree_validate_node(t->root, NULL);
}
ASSERT(btree_count == t->count);
#endif
}
/*****************************************************************************/
/* Utility functions */
/*****************************************************************************/
static btree_node_t*
btree_min(btree_node_t *x)
{
if (x == NULL) {
return NULL;
}
while(x->left) {
x = x->left;
}
return x;
}
static btree_node_t*
btree_max(btree_node_t *x)
{
if (x == NULL) {
return NULL;
}
while(x->right) {
x = x->right;
}
return x;
}
static btree_node_t*
btree_successor(btree_node_t *x)
{
btree_node_t *y;
if (x->right != NULL) {
return btree_min(x->right);
}
y = x->parent;
while (y != NULL && x == y->right) {
x = y;
y = y->parent;
}
return y;
}
static btree_node_t*
btree_search(btree_node_t *x, uint32_t key)
{
while (x != NULL && key != x->key) {
if (key < x->key) {
x = x->left;
} else {
x = x->right;
}
}
return x;
}
static void
btree_insert_node(btree_t *tree, btree_node_t *z) {
btree_node_t *x, *y;
btree_validate(tree);
y = NULL;
x = tree->root;
while (x != NULL) {
y = x;
ASSERT(z->key != x->key);
if (z->key < x->key) {
x = x->left;
} else {
x = x->right;
}
}
z->parent = y;
if (y == NULL) {
tree->root = z;
} else if (z->key < y->key) {
y->left = z;
} else {
y->right = z;
}
tree->count++;
btree_validate(tree);
}
static btree_node_t*
btree_delete_node(btree_t *tree, btree_node_t *z)
{
btree_node_t *x, *y;
btree_validate(tree);
if (z->left == NULL || z->right == NULL) {
y = z;
} else {
y = btree_successor(z);
}
if (y->left != NULL) {
x = y->left;
} else {
x = y->right;
}
if (x != NULL) {
x->parent = y->parent;
}
if (y->parent == NULL) {
tree->root = x;
} else if (y == y->parent->left) {
y->parent->left = x;
} else {
y->parent->right = x;
}
z->key = y->key;
z->data = y->data;
tree->count--;
btree_validate(tree);
return y;
}
/*****************************************************************************/
/* Exported functions */
/*****************************************************************************/
int
btree_create(btree_t **tree)
{
btree_t *t = (btree_t*)xmalloc(sizeof(btree_t));
if (t) {
t->count = 0;
t->magic = BTREE_MAGIC;
t->root = NULL;
*tree = t;
return TRUE;
}
return FALSE;
}
int
btree_destroy(btree_t **tree)
{
btree_t *t = *tree;
btree_validate(t);
if (t->root != NULL) {
debug_msg("Tree not empty - cannot destroy\n");
return FALSE;
}
xfree(t);
*tree = NULL;
return TRUE;
}
int
btree_find(btree_t *tree, uint32_t key, void **d)
{
btree_node_t *x;
btree_validate(tree);
x = btree_search(tree->root, key);
if (x != NULL) {
*d = x->data;
return TRUE;
}
return FALSE;
}
int
btree_add(btree_t *tree, uint32_t key, void *data)
{
btree_node_t *x;
btree_validate(tree);
x = btree_search(tree->root, key);
if (x != NULL) {
debug_msg("Item already exists - key %ul\n", key);
return FALSE;
}
x = (btree_node_t *)xmalloc(sizeof(btree_node_t));
x->key = key;
x->data = data;
x->parent = NULL;
x->left = NULL;
x->right = NULL;
x->magic = BTREE_NODE_MAGIC;
btree_insert_node(tree, x);
return TRUE;
}
int
btree_remove(btree_t *tree, uint32_t key, void **data)
{
btree_node_t *x;
btree_validate(tree);
x = btree_search(tree->root, key);
if (x == NULL) {
debug_msg("Item not on tree - key %ul\n", key);
*data = NULL;
return FALSE;
}
/* Note value that gets freed is not necessarily the the same
* as node that gets removed from tree since there is an
* optimization to avoid pointer updates in tree which means
* sometimes we just copy key and data from one node to
* another.
*/
*data = x->data;
x = btree_delete_node(tree, x);
xfree(x);
return TRUE;
}
int
btree_get_min_key(btree_t *tree, uint32_t *key)
{
btree_node_t *x;
btree_validate(tree);
if (tree->root == NULL) {
return FALSE;
}
x = btree_min(tree->root);
if (x == NULL) {
return FALSE;
}
*key = x->key;
return TRUE;
}
int
btree_get_max_key(btree_t *tree, uint32_t *key)
{
btree_node_t *x;
btree_validate(tree);
if (tree->root == NULL) {
return FALSE;
}
x = btree_max(tree->root);
if (x == NULL) {
return FALSE;
}
*key = x->key;
return TRUE;
}
int
btree_get_next_key(btree_t *tree, uint32_t cur_key, uint32_t *next_key)
{
btree_node_t *x;
btree_validate(tree);
x = btree_search(tree->root, cur_key);
if (x == NULL) {
return FALSE;
}
x = btree_successor(x);
if (x == NULL) {
return FALSE;
}
*next_key = x->key;
return TRUE;
}
/*****************************************************************************/
/* Test code */
/*****************************************************************************/
#ifdef TEST_BTREE
static int
btree_depth(btree_node_t *x)
{
int l, r;
if (x == NULL) {
return 0;
}
l = btree_depth(x->left);
r = btree_depth(x->right);
if (l > r) {
return l + 1;
} else {
return r + 1;
}
}
#include <curses.h>
static void
btree_dump_node(btree_node_t *x, int depth, int c, int w)
{
if (x == NULL) {
return;
}
move(depth * 2, c);
printw("%lu", x->key);
refresh();
btree_dump_node(x->left, depth + 1, c - w/2, w/2);
btree_dump_node(x->right, depth + 1, c + w/2, w/2);
return;
}
static void
btree_dump(btree_t *b)
{
initscr();
btree_dump_node(b->root, 0, 40, 48);
refresh();
endwin();
}
#include "stdlib.h"
int
main()
{
btree_t *b;
uint32_t i, *x;
uint32_t v[] = {15, 5, 16, 3, 12, 20, 10, 13, 18, 23, 6, 7};
uint32_t nv = sizeof(v) / sizeof(v[0]);
btree_create(&b);
for(i = 0; i < nv; i++) {
x = (uint32_t*)xmalloc(sizeof(uint32_t));
*x = (uint32_t)random();
if (btree_add(b, v[i], (void*)x) != TRUE) {
printf("Fail Add %lu %lu\n", v[i], *x);
}
}
printf("depth %d\n", btree_depth(b->root));
btree_dump(b);
sleep(3);
btree_remove(b, 5, (void*)&x);
btree_dump(b);
sleep(3);
btree_remove(b, 16, (void*)&x);
btree_dump(b);
sleep(3);
btree_remove(b, 13, (void*)&x);
btree_dump(b);
while (btree_get_root_key(b, &i)) {
if (btree_remove(b, i, (void*)&x) == FALSE) {
fprintf(stderr, "Failed to remove %lu\n", i);
}
btree_dump(b);
sleep(1);
}
if (btree_destroy(&b) == FALSE) {
printf("Failed to destroy \n");
}
return 0;
}
#endif /* TEST_BTREE*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -