算法导论代码 第18章 B树

来源:互联网 发布:网站的源码如何查看 编辑:程序博客网 时间:2024/05/02 00:04

18章 B

#include <stdio.h>#include <stdbool.h>#include <string.h>#include <stdlib.h>#include <time.h>/*两个约定:(1)B树的根结点始终在主存中,因而无需对根做DISK_READ,  但是根结点被改变后,都需要对根结点做一次DISK_WRITE(2)任何被当作参数的结点被传递之前,要先对它们做一次DISK_READ*/#define DISK_READ(x)#define DISK_WRITE(x)/*B树的最小度数*/enum { tree_degree = 3 };typedef struct tree_type *tree;struct tree_node {int num;void **key;struct tree_node **child;bool leaf;};struct tree_type {int (*comp) (const void *, const void *);struct tree_node *root;};void tree_node_ini(struct tree_node *n, int num, bool leaf){n->num = num;n->leaf = leaf;int full_key_num = 2 * tree_degree - 1;int full_child_num = full_key_num + 1;n->key = malloc(sizeof(void *) * full_key_num);memset(n->key, 0, sizeof(void *) * full_key_num);n->child = malloc(sizeof(struct tree_node *) * full_child_num);memset(n->child, 0, sizeof(struct tree_node *) * (full_child_num));}void tree_node_delete_key_child(struct tree_node *x, int key_pos, int child_pos){memmove(&x->key[key_pos], &x->key[key_pos + 1],sizeof(void *) * (x->num - key_pos - 1));memmove(&x->child[child_pos], &x->child[child_pos + 1],sizeof(struct tree_node *) * (x->num - child_pos));--x->num;}void tree_node_insert_key_child(struct tree_node *x, void *key, int key_pos,struct tree_node *child, int child_pos){memmove(&x->key[key_pos], &x->key[key_pos + 1],sizeof(void *) * (x->num - key_pos));x->key[key_pos] = key;memmove(&x->child[child_pos], &x->child[child_pos + 1],sizeof(struct tree_node *) * (x->num + 1 - child_pos));x->child[child_pos] = child;++x->num;}tree tree_create(int (*comp) (const void *, const void *)){tree t = malloc(sizeof(struct tree_type));t->comp = comp;struct tree_node *x = malloc(sizeof(struct tree_node));tree_node_ini(x, 0, true);DISK_WRITE(x);t->root = x;return t;}void tree_node_destroy(struct tree_node *x){free(x->key);free(x->child);free(x);}void tree_destroy_all_node(struct tree_node *x, void (*free_key) (void *)){if (x == NULL)return;for (int i = 0; i < x->num + 1; ++i) {tree_destroy_all_node(x->child[i], free_key);}for (int i = 0; i < x->num; i++) {free_key(x->key[i]);}free(x->key);free(x->child);free(x);}void tree_destroy(tree t, void (*free_key) (void *)){tree_destroy_all_node(t->root, free_key);free(t);}struct tree_node *tree_search(tree t, struct tree_node *x, void *key,      int *index){int i = 0;while (i < x->num && t->comp(key, x->key[i]) > 0) {++i;}if (i < x->num && t->comp(key, x->key[i]) == 0) {*index = i;return x;}if (x->leaf) {return NULL;} else {DISK_READ(x->child[i]);return tree_search(t, x->child[i], key, index);}}//前序遍历void tree_preorder_walk(struct tree_node *x, int depth,void (*handle) (const void *)){if (x != NULL) {printf("depth:%d ", depth);printf("key:(");for (int i = 0; i < x->num; i++) {handle(x->key[i]);if (i < x->num - 1) {printf(",");}}printf(")\n");for (int i = 0; i < x->num + 1; ++i) {tree_preorder_walk(x->child[i], depth + 1, handle);}}}void tree_split_child(struct tree_node *x, int i, struct tree_node *y){struct tree_node *z = malloc(sizeof(struct tree_node));tree_node_ini(z, tree_degree - 1, y->leaf);memcpy(z->key, &y->key[tree_degree],       sizeof(void *) * (tree_degree - 1));if (!y->leaf) {memcpy(z->child, &y->child[tree_degree],       sizeof(struct tree_node *) * tree_degree);}y->num = tree_degree - 1;tree_node_insert_key_child(x, y->key[tree_degree - 1], i, z, i + 1);DISK_WRITE(y);DISK_WRITE(z);DISK_WRITE(x);}void tree_union_child(tree t, struct tree_node *x, int i, struct tree_node *y,      struct tree_node *z){void *key = x->key[i];y->key[y->num] = key;memcpy(&y->key[y->num + 1], z->key, sizeof(void *) * z->num);memcpy(&y->child[y->num + 1], z->child, sizeof(void *) * (z->num + 1));y->num += z->num + 1;tree_node_delete_key_child(x, i, i + 1);tree_node_destroy(z);//把z释放掉                DISK_WRITE(y);DISK_WRITE(x);if (x == t->root && x->num == 0)//如果x是根,并没有元素了{t->root = y;tree_node_destroy(x);}}void tree_insert_not_full(tree t, struct tree_node *x, void *key){int i = x->num - 1;if (x->leaf) {while (i >= 0 && t->comp(key, x->key[i]) < 0) {x->key[i + 1] = x->key[i];--i;}x->key[i + 1] = key;++x->num;DISK_WRITE(x);return;}while (i >= 0 && t->comp(key, x->key[i]) < 0) {--i;}++i;DISK_READ(x->child[i]);if (x->child[i]->num == 2 * tree_degree - 1) {tree_split_child(x, i, x->child[i]);if (t->comp(key, x->key[i]) > 0) {++i;}}tree_insert_not_full(t, x->child[i], key);}void tree_insert(tree t, void *key){struct tree_node *r = t->root;if (r->num == 2 * tree_degree - 1) {struct tree_node *s = malloc(sizeof(struct tree_node));tree_node_ini(s, 0, false);t->root = s;s->child[0] = r;tree_split_child(s, 0, r);tree_insert_not_full(t, s, key);} else {tree_insert_not_full(t, r, key);}}struct tree_node *tree_successor(struct tree_node *x){while (x != NULL && x->child[0] != NULL) {x = x->child[0];}return x;}struct tree_node *tree_predecessor(struct tree_node *x){while (x != NULL && x->child[x->num] != NULL) {x = x->child[x->num];}return x;}void swap(void *a, void *b, size_t elem_size){if (a == NULL || b == NULL || a == b)return;char temp[elem_size];/*变长数组 */memcpy(temp, a, elem_size);memcpy(a, b, elem_size);memcpy(b, temp, elem_size);}struct tree_node *tree_delete(tree t, struct tree_node *x, void *key, int *i);//情况1,如果关键字k在结点x中而且x是个叶结点struct tree_node *tree_delete_from_leaf(struct tree_node *x, int *i){void *key = x->key[*i];tree_node_delete_key_child(x, *i, *i);x->key[x->num] = key;*i = x->num;//i保存了删掉的key的位置return x;}//情况2,如果关键字k在结点x中而且x是个内结点struct tree_node *tree_delete_from_node(tree t, struct tree_node *x, void *key,int *i){struct tree_node *y = x->child[*i];//情况2a,结点x中前于k的子结点y包含至少tree_degree个关键字if (y->num >= tree_degree) {struct tree_node *predecessor = tree_predecessor(y);swap(&x->key[*i], &predecessor->key[predecessor->num - 1],     sizeof(void *));*i = predecessor->num - 1;return tree_delete_from_leaf(predecessor, i);}struct tree_node *z = x->child[*i + 1];//情况2b,结点x中位于k之后的子结点包含至少tree_degree个关键字if (z->num >= tree_degree) {struct tree_node *successor = tree_successor(y);swap(&x->key[*i], &successor->key[0], sizeof(void *));*i = 0;return tree_delete_from_leaf(successor, i);}//情况2c,y和z都只有tree_degree-1个关键字tree_union_child(t, x, *i, y, z);return tree_delete(t, y, key, i);}//如果关键字k不在内结点x中,则确定必包含k的正确的子树的根cstruct tree_node *tree_delete_from_child(tree t, struct tree_node *x, void *key, int *i){DISK_READ(x->child[i]);struct tree_node *p_child = x->child[*i];if (p_child->num >= tree_degree) {return tree_delete(t, p_child, key, i);}//情况3a,p_child只包含tree_degree-1个关键字struct tree_node *y = NULL;//p_child不是最左子结点,则有左兄弟if (*i > 0) {DISK_READ(x->child[*i - 1]);y = x->child[*i - 1];}if (y != NULL && y->num >= tree_degree) {tree_node_insert_key_child(p_child, x->key[*i - 1], 0,   y->child[y->num], 0);x->key[*i - 1] = y->key[y->num - 1];tree_node_delete_key_child(y, y->num - 1, y->num);return tree_delete(t, p_child, key, i);}struct tree_node *z = NULL;//p_child不是最右子结点,则有右兄弟if (*i < x->num) {DISK_READ(x->child[*i + 1]);z = x->child[*i + 1];}if (z != NULL && z->num >= tree_degree) {tree_node_insert_key_child(p_child, x->key[*i],   p_child->num, z->child[0],   p_child->num + 1);x->key[*i] = z->key[0];tree_node_delete_key_child(z, 0, 0);return tree_delete(t, p_child, key, i);}//情况3b,p_child及其兄弟都包含tree_degree-1个关键字,p_chaild合并进左兄弟if (y != NULL) {tree_union_child(t, x, *i - 1, y, p_child);return tree_delete(t, y, key, i);}//情况3b,p_child及其兄弟都包含tree_degree-1个关键字,右兄弟合并进p_childif (z != NULL) {tree_union_child(t, x, *i, p_child, z);return tree_delete(t, p_child, key, i);}return NULL;}struct tree_node *tree_delete(tree t, struct tree_node *x, void *key, int *i){*i = 0;while (*i < x->num && t->comp(key, x->key[*i]) > 0) {++*i;}if (*i < x->num && t->comp(key, x->key[*i]) == 0) {if (x->leaf) {return tree_delete_from_leaf(x, i);} else {return tree_delete_from_node(t, x, key, i);}}return tree_delete_from_child(t, x, key, i);}int cmp_int(const void *p1, const void *p2){const int *pa = p1;const int *pb = p2;if (*pa < *pb)return -1;if (*pa == *pb)return 0;return 1;}void print_key(const void *key){const int *p = key;printf("%d", *p);}int main(){printf("minimum degree of the B-tree:%d\n", tree_degree);tree t = tree_create(cmp_int);for (int i = 0; i < 20; i++) {int *p = malloc(sizeof(int));*p = i;tree_insert(t, p);}printf("前序遍历:\n");tree_preorder_walk(t->root, 0, print_key);int index;int key = 0;struct tree_node *p = tree_search(t, t->root, &key, &index);if (p != NULL) {printf("查找关键字:%d成功\n", key);printf("删除关键字:%d\n", key);struct tree_node *del = tree_delete(t, t->root, &key, &index);if (del != NULL) {free(del->key[index]);}p = tree_search(t, t->root, &key, &index);if (p == NULL) {printf("删除关键字:%d成功\n", key);}printf("删除后,前序遍历:\n");tree_preorder_walk(t->root, 0, print_key);}tree_destroy(t, free);return 0;}