B-树

B-树(Balance Tree)一个m阶的B树具有如下几个特征:

  1. 每个结点最多有m-1个关键字。
  2. 根结点最少可以只有1个关键字。
  3. 非根结点至少有Math.ceil(m/2)-1个关键字。
  4. 每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。
  5. 所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。
  6. 每个节点中的关键字从小到大排列,节点当中关键字正好是子节点包含的关键字的值域分划。

特征解释:

如:这是一个3阶的B树,

 

1.每个结点最多有2个关键字。

 

2.根结点(9)最少可以只有1个关键字。

 

3.非根结点至少有1个关键字

 

4.满足每个节点中的关键字小到大排列

 

5.叶子节点1,(3,5),8,11,(13,15) 位于同一层

 

6.子节点的关键字数值范围包含节点中的元素的数值:如(2,6)在1-8中间 12在11-15中间 9在1-12之间

查找: 2-3的3阶树 和 2-3-4的4阶树 是个特殊例子 (和二叉树优点类似)

第1次磁盘IO:

在内存中定位(和9比较):5小于9,走左边

第2次磁盘IO

在内存中定位(和2,6比较):5介于2-6之间 走中间

第3次磁盘IO:

在内存中定位(和3,5比较): 5被成功找到

B树的主要的特点就是减少磁盘IO消耗,尽量采用内存进行数值比较,区别于二叉树的“高瘦“ B树则是采用”矮胖“减少了IO的次数,增多了内存交互,不过内存之间交互速度是很快的,消耗可以微乎其微,查询性能要高于二叉树。

不过B树的查询特点和二叉树是相似的,遵循小于走左边,大于走右边,区别于3阶和4阶不同的是,既不大于又不小于走中间 (如上图3阶B树)

插入: 这里插入元素4

程:

自上而下做对比,和查询同原理,发现4应该插入到(3,5)之间,但是(3,5)已经是有2个关键字了,(3,4,5)关键字撑爆了,根据中位数(4)分裂,中位数(4)往上抛

往上抛,插入到(2,6)->(2,4,6) 同样关键字撑爆了,根据中位数(4)分裂,进行中位数(4)往上抛

所以再往上抛,就形成了(4,9) 由于B树的自平衡(优势体现),在满足B树的规则条件,就形成了如下:

删除: 删除11

自上而下和查询同原理找到11的位置

删除11后,节点12只有一个孩子,不符合B树规范。这里采用左旋转(如果左右兄弟存在,则间接向左右兄弟借关键码),上浮和下沉保持平衡,如果无法左旋,那么就通过父节点下溢兄弟节点合并实现平衡

详细例子:https://xiangou.blog.csdn.net/article/details/80097201

 

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 Python 实现 B-的代码: ```python class BTreeNode: def __init__(self, leaf=False): self.leaf = leaf self.keys = [] self.child = [] class BTree: def __init__(self, t): self.root = BTreeNode(True) self.t = t def search(self, k, x=None): if isinstance(x, BTreeNode): i = 0 while i < len(x.keys) and k > x.keys[i]: i += 1 if i < len(x.keys) and k == x.keys[i]: return (x, i) elif x.leaf: return None else: return self.search(k, x.child[i]) else: return self.search(k, self.root) def insert(self, k): r = self.root if len(r.keys) == (2*self.t) - 1: s = BTreeNode() self.root = s s.child.insert(0, r) self._split_child(s, 0) self._insert_nonfull(s, k) else: self._insert_nonfull(r, k) def _insert_nonfull(self, x, k): i = len(x.keys) - 1 if x.leaf: x.keys.append(0) while i >= 0 and k < x.keys[i]: x.keys[i+1] = x.keys[i] i -= 1 x.keys[i+1] = k else: while i >= 0 and k < x.keys[i]: i -= 1 i += 1 if len(x.child[i].keys) == (2*self.t) - 1: self._split_child(x, i) if k > x.keys[i]: i += 1 self._insert_nonfull(x.child[i], k) def _split_child(self, x, i): t = self.t y = x.child[i] z = BTreeNode(y.leaf) x.child.insert(i+1, z) x.keys.insert(i, y.keys[t-1]) z.keys = y.keys[t:(2*t - 1)] y.keys = y.keys[0:(t-1)] if not y.leaf: z.child = y.child[t:(2*t)] y.child = y.child[0:(t-1)] def __repr__(self): return '<BTree:t='+str(self.t)+',root='+str(self.root)+'>' ``` 这个实现中,`BTreeNode` 表示 B 的节点,其中 `keys` 是节点中存储的关键字,`child` 是节点的子节点。`BTree` 表示整个 B ,其中 `root` 是根节点,`t` 是 B 的参数。 函数 `search` 可以在 B 中查找关键字,函数 `insert` 可以插入新的关键字。函数 `_insert_nonfull` 是插入关键字的内部实现,函数 `_split_child` 是分裂节点的内部实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值