[数据结构]B树的基本定义和操作

B树

B树的定义

  • 多叉搜索树,每个节点最多有M个子树,M-1个关键字
  • 根节点若非唯一节点,则最少有2个子树,即最少有1个关键字
  • 非根节点也非叶子节点的,最少有ceil(M/2)个子树,ceil(M/2)-1个关键字
  • 叶子节点都在树的同一层
  • 每个节点的关键字从小到大排列,充当划分子树的边界
c 复制代码
// B树的结构体如下:
typedef struct _btree_node {
	int *keys;
	struct _btree_node **childrens;
	int num;  // 有多少个关键字

	int leaf; // 是否是叶子节点
} btree_node;

typedef struct _btree {
	struct _btree_node *root;
	int t;  // ceil(M/2)-1,方便B树的分裂和合并操作
} btree;

B树的节点生成和销毁

c 复制代码
btree_node *btree_node_create(int t, int leaf)
{
	btree_node *node = calloc(1, sizeof(btree_node ));
	node->keys= calloc(2*t-1, sizeof(int));
	node->childrens = calloc(2*t, sizeof(btree_node *));
	node->num = 0;
	node->leaf = leaf;
	return node;
}

void btree_node_destroy(btree_node *node)
{
	free(node->keys);
	free(node->childrens);
	free(node);
}

B树的分裂

c 复制代码
void btree_split_child(btree *T, btree_node *x, int idx) {
	btree_node *y = x->childrens[idx];
	int t = T->t;
	btree_node *z = btree_node_create(t, y->leaf);

	for (int i = 0; i < t - 1; i++) {
		z->keys[i] = y->keys[i+t];
	}
	if (y->leaf == 0) {
		for (int i = 0; i < t; i++) {
			z->childrens[i] = y->chiledrens[i+t];
		}
	}
	z->num = t - 1;
	y->num = t - 1;

	for (int i = x->num; i > idx; i--) {
		x->keys[i] = x->keys[i-1];
		x->childrens[i+1] = x->childrens[i];
	}
	x->keys[idx] = y->keys[t-1];
	x->childrens[idx+1] = z;
	x->num += 1;
}

B树的合并

c 复制代码
void btree_merge(btree *T, btree_node *x, int idx) {
	btree_node *y = x->childrens[idx];
	btree_node *z = x->childrens[idx+1];

	int t = T->t;
	for (int i = 0; i < t - 1; i++) {
		y->keys[i+t] = z->keys[i];
	}
	y->keys[t - 1] = x->keys[idx];

	if (z->leaf == 0) {
		for (int i = 0; i < t; i++) {
			y->childrens[i+t] = z->childrens[i];
		}
	}
	y->num += t;
	btree_node_destroy(z);

	for (int i = idx + 1; i < x->num; i++) {
		x->keys[i-1] = x->keys[i];
		x->childrens[i] = x->childrens[i+1];
	}
	x->num -= 1;
}
相关推荐
用户2204603958685 小时前
HBuilder + uniapp 项目切换到VsCode
前端框架
薛定喵的谔5 小时前
我开源了一个精致的 Next.js 博客模板:Skyplume
前端·前端框架·next.js
星栈9 小时前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:再把新建、编辑和交付补上
前端·rust·前端框架
donecoding13 小时前
3 条命令搞定闭环 Monorepo:Lerna 版本管理 + 拓扑构建 + 自定义分发
前端·前端框架·node.js
星栈2 天前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:第一版先把列表和详情跑通
前端·rust·前端框架
下家2 天前
我放弃了 Vue/React,选择自研框架
前端·前端框架
刘马想放假2 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
hoLzwEge2 天前
pnpm-lock.yaml
前端框架
星栈3 天前
Dioxus 接数据库最容易写歪的 3 个地方:sqlx + SQLite 怎么接才顺
前端·rust·前端框架
星栈3 天前
Dioxus 表单处理:从输入、校验到文件上传,一条链路讲透
前端·rust·前端框架