📄 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 0x01010101static int btree_count;static voidbtree_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 voidbtree_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 voidbtree_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 *//*****************************************************************************/intbtree_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;}intbtree_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;}intbtree_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;}intbtree_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;}intbtree_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_BTREEstatic intbtree_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 voidbtree_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 voidbtree_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 + -