JavaScript B+树

本文介绍了B+树的构造过程,从二叉查找树到多叉树的转变,强调了如何通过降低树的高度来减少磁盘IO操作。在B+树中,节点作为索引,数据存储在叶子节点的链表中,便于区间查找。此外,文章讨论了节点分裂与合并策略,以保持节点数量在页大小范围内,确保高效的数据访问。
摘要由CSDN通过智能技术生成
/**
 * B+树的构造
 * 
 * 
 * 1、第一步 改造二叉查找树(左边的子节点比当前节点小,右边的子节点比当前节点大)
 * 树中的节点并不存储数据本身,而是只作为索引,然后再每个叶子节点串在一条链表上,链表中
 * 的数据是从小到大有序的。
 * 改造以后,只要拿着区间的起始值在树中进行查找,当查找到某个叶子节点的时候,顺着链表往后遍历,
 * 直到链表中的结点数据值大于区间的终点值。那么遍历到的数据,就是符合区间值的所有数据。
 * 
 * 2、第二步 降低树的高度 减少读取节点的操作 从而减少磁盘IO操作
 * 将二叉树 构建成五叉树索引,那么高度只有2,查找一个数据,对应只要2次磁盘操作。
 * 
 */

 

 

/** * 那么,如何改造成五叉树呢?
 * 
 * 首先m叉树中的非叶子节点中,有三个属性,分别记录是几叉树,记录简直用来划分数据区间,记录指向子节点的指针
 * 
 * 首先,keywords记录的是m-1个键值,用来将下级索引节点分到m个区间,也就是m叉树
 * 
 */
class BPlusTreeNode{
    constructor(m){
        this.m = m;
        this.keywords = new Array(m-1);
        this.children = new Array(m);
        for(let i = 0;i<m;i++){
            this.children[i] = new BPlusTreeNode(m);
        }
    }
}
/**
 * 其次 m叉树中的叶子节点中,存储的是节点对应的值,而不是区间
 */
class BPlusTreeLeafNode{
    constructor(k){
        this.k = k;//这里的k对应下图中的a b c中有3个存储的数据
        this.keywords = new Array(k);//这里的keywords用来划分下面a b c三个区间
        this.dataAdress = new Array(k);//数据地址(或者直接指向数据)
        this.prev = new BPlusTreeLeafNode(k);//最终层中链表的前驱节点
        this.next = new BPlusTreeLeafNode(k);//最终层中链表的后继节点
    }
}

 

/**
 * 对于b+树来说,m的值是根据页的大小事先计算好多,也就是说每个节点最多只能有m个子节点。
 * 但是在不断树更新的过程中,有可能使得某些节点的子节点个数超过m,这个节点的大小超过了
 * 一个页的大小,读取这样的一个系欸但,就会导致多次的磁盘IO操作。
 * 此时我们只需要将这个节点分裂成两个节点,不断的向上级联分裂,一直到根节点.
 *在删除节点的时候,也会导致某些节点中,子节点的个数变得非常少。
 此时,我们可以设置一个阈值,在B+树中,这个阈值等于m/2,如果某个节点个数小于m/2,我们就
 将它跟相邻的兄弟节点合并。不过合并之后节点的子节点个数有可能会超过m。此时又可以像
 刚才说的分裂节点一样,不断的向上级分裂。
 */

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的B+树算法javascript实现: ```javascript class BPlusTreeNode { constructor(order, isLeaf = false) { this.order = order; this.isLeaf = isLeaf; this.keys = []; this.children = []; this.next = null; } isFull() { return this.keys.length === this.order; } split() { const mid = Math.ceil(this.order / 2) - 1; const left = new BPlusTreeNode(this.order, this.isLeaf); const right = new BPlusTreeNode(this.order, this.isLeaf); left.keys = this.keys.slice(0, mid); right.keys = this.keys.slice(mid); if (this.isLeaf) { left.next = right; left.children = this.children.slice(0, mid); right.children = this.children.slice(mid); } else { left.children = this.children.slice(0, mid + 1); right.children = this.children.slice(mid + 1); } return { left, right, median: this.keys[mid] }; } } class BPlusTree { constructor(order) { this.order = order; this.root = new BPlusTreeNode(order, true); } insert(key, value) { let node = this.root; if (node.isFull()) { this.root = new BPlusTreeNode(this.order); this.root.children.push(node); const { left, right, median } = node.split(); this.root.keys.push(median); this.root.children[0] = left; this.root.children[1] = right; node = key > median ? right : left; } let parent; while (!node.isLeaf) { parent = node; node = key > parent.keys[parent.keys.length - 1] ? parent.children[parent.keys.length] : parent.children.find((child, index) => key < parent.keys[index]); if (node.isFull()) { const { left, right, median } = node.split(); parent.children[parent.children.indexOf(node)] = left; parent.children.splice(parent.children.indexOf(left) + 1, 0, right); parent.keys.splice(parent.children.indexOf(left), 0, median); node = key > median ? right : left; } } node.keys.push(key); node.children.push(value); } search(key) { let node = this.root; while (!node.isLeaf) { node = node.children.find((child, index) => key <= node.keys[index]); } return node.children[node.keys.indexOf(key)]; } } ``` 这个实现使用了两个类,一个是BPlusTreeNode表示B+树的节点,一个是BPlusTree表示整个B+树。在BPlusTreeNode类中实现了分裂节点、判断节点是否已满、获取节点的中间值等方法。在BPlusTree类中实现了插入和查找操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值