/**
* 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。此时又可以像
刚才说的分裂节点一样,不断的向上级分裂。
*/