手撕B树

B树是一种多路查找树,广泛应用于数据库和文件系统中。本文介绍了B树的特点,包括每个节点最多存储m-1个数据节点和最多m个子节点,以及其构造规则和插入操作,特别强调了B+树与B树的区别。通过裂变操作确保插入过程满足B树的特性。
摘要由CSDN通过智能技术生成

B树

B树和B+树都是多路查找树。具备分支多层数少的优点常用于数据库索引存储
BTree大量应用在数据库(mongodb)和文件系统当中,B+Tree经常用于数据库索引(空间局部性原理)
B树代表每个节点可存储的数据节点不超过m-1,且每个节点的子节点不超过m个的树。根节点的子节点为0或至少为2
B+树与B树区别就是B+树只在没有子节点的底层节点存储数据而其他包含子节点的父节点都是不存储数据值存储索引值
假设m为4我们就说这是一颗4叉的B树,其每个节点可以存储最多3个数据节点,最多含有4个子节点

特点

数据保存在节点
一个节点可以至有多m-1个数据节点
根结点如果有子女则至少有两个子女
除根结点以外的所有结点(不包括叶子结点)的度数正好是当前结点保存的数据节点总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m
所有的叶子结点都位于同一层。(叶子节点指的是指向null)
每个非根节点所包含的数据节点个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;// ┌m/2┐ ==》m/2向上取整

结构图

b-tree

构造B树

我们先了解下其几点重要构建要求
1.保持所有的叶子结点都位于同一层
2.一个节点可以至有多m-1个数据节点
3.每个非根节点所包含的数据节点个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;// ┌m/2┐ ==》m/2向上取整
基于这些条件,B树的插入是从底部插入,先假设可以直接插入找到的节点,这时不破坏要求1
插入后因为新增数据节点如果破坏了要求2,进行裂变
裂变为了满足要求3从中间裂变
裂变出来的节点插入当前结点父节点(递归操作),因为是向上裂变插入,所以不破坏规则1

代码实现

可以保存多个数据节点的节点类

	class MultiNode{
   
		int nodeCounter = 0;//数据节点总数
		Node head;//数据节点链表头
		Node tail;//数据节点链表尾
		MultiNode parent;//父节点
		Node greaterParent;//大于当前节点的数据节点
		Node lesserParent;//小于当前节点的数据节点
	}

数据节点类

	class Node{
   
		int num;//索引大小
		MultiNode greater;//大于
		MultiNode lesser;//小于
		Node prev;
		Node next;
	}

裂变操作

	private Node fissAndReturnBreakNode(MultiNode multiNode,int breakPoint) {
   
		if(breakPoint<1 || breakPoint>=multiNums) {
   
			return null;
		}
		//裂变
		if(multiNode.greaterParent!=null) {
   
			//父节点断开
			multiNode.greaterParent.lesser = null;
			multiNode.greaterParent = null;
		}
		if(multiNode.lesserParent!=null) {
   
			//父节点断开
			multiNode.lesserParent.greater = null;
			multiNode.lesserParent = null;
		}
		Node beakNode = multiNode.head;
		for(int i=0;i<breakPoint;i++)
			beakNode = beakNode.next;
		MultiNode newMultiNode = new MultiNode();
		newMultiNode.head = beakNode.next;
		newMultiNode.tail = multiNode.tail;
		multiNode.tail = beakNode.prev;
		newMultiNode.nodeCounter = multiNode.nodeCounter - breakPoint -1;
		multiNode.nodeCounter = breakPoint;
		beakNode.next = beakNode.prev = newMultiNode.head.prev = multiNode.tail.next = null;
		if(beakNode.lesser!=null) {
   
			beakNode.lesser.lesserParent = multiNode.tail;
			multiNode.tail.greater = beakNode.lesser;
		}
		if(beakNode.greater!=null) {
   
			beakNode.greater.greaterParent = newMultiNode.head;
			newMultiNode.head.lesser = beakNode.greater;
		}
		beakNode.lesser = multiNode;
		multiNode.greaterParent = beakNode;
		beakNode.greater = newMultiNode;
		newMultiNode.lesserParent = beakNode
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值