算法导论代码 第18章 B树

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的正确的子树的根c
struct 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_child
	if (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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值