B-tree B树的JS实现(一):添加元素

话不多说,直接上代码。B树的理论网上太多了,大家自行查找学习吧

const M = 3;

class BTree {
    constructor() {
        /*只需要入口节点,即根节点*/
        this.root = null;
    }
    addKey(key){
        if(this.root === null){
            this.root = new BTreeNode();
            this.root.add(key);
            return 1;
        }
        if(this.root.pages.length === 0){
            this.root.add(key);
            return 1;
        }
        /*一直遍历到叶子节点*/
        let node = this.root;
        while(node.pages.length > 0){
            for(let i in node.keys){
                i = parseInt(i);
                if(key === node.keys[i]){
                    return 0;
                }
                if(key < node.keys[i]){
                    node = node.pages[i];
                    break;
                }else if (key > node.keys[node.keys.length - 1]){
                    node = node.pages[node.pages.length - 1];
                    break;
                }else{
                    node = node.pages[i+1];
                    break;
                }
            }
        }
        node.add(key);
        return 1;
    }
}

class BTreeNode {
    constructor() {
        this.parent = null;
        this.keys = [];
        this.pages = [];
    }
    add(key){
        if(this.keys.length === 0){
            this.keys.push(key);
            return this.keys.length;
        }
        if(this.keys[0] > key){
            /*插入头部*/
            this.keys.unshift(key);
        }else if(this.keys[this.keys.length - 1] < key){
            /*插入尾部*/
            this.keys.push(key);
        }else{
            /*插入中间*/
            for(let i in this.keys){
                if(key < this.keys[i+1] && key > this.keys[i]){
                    this.keys.splice(i, 0, key);
                }
            }
        }
        if(this.keys.length <= M - 1){
            return this.keys.length;
        }
        /*一个节点数ceil(M/2) + 1 <= n <= M - 1*/
        /*当节点数满了后,需要分裂*/
        /*第一种分裂方式,中间的关键字上移
        * ,左右的关键字变成左右子
        * 每次插入的时候肯定都是子节点
        *
        * 分裂后,又可能导致非叶子节点的查出从而导致非叶子节点分裂
        * */
        if(this.parent == null){
            let leftChild = new BTreeNode();
            let rightChild = new BTreeNode();
            leftChild.keys = this.keys.slice(0, Math.floor(this.keys.length/2));
            rightChild.keys = this.keys.slice(Math.floor(this.keys.length/2) + 1, this.keys.length);
            leftChild.parent = this;
            rightChild.parent = this;
            this.keys = [this.keys[Math.floor(this.keys.length/2)]];
            leftChild.pages = this.pages.slice(0, Math.floor(this.pages.length/2));
            rightChild.pages = this.pages.slice(Math.floor(this.pages.length/2), this.pages.length);
            this.pages = [leftChild, rightChild];
        }else{
            /*先将新建的节点连接好,顺序不能错,否则分裂时丢失节点*/
            /*先将一半的key分出去*/
            let leftChild = new BTreeNode();
            leftChild.keys = this.keys.slice(0, Math.floor(this.keys.length/2));
            leftChild.parent = this.parent;
            for(let i in this.parent.pages){
                i = parseInt(i);
                /*将新建的节点连接到父节点的pages上*/
                if(this.parent.pages[i] === this){
                    this.parent.pages.splice(i, 0, leftChild);
                    break;
                }
            }

            /*中间的key给父节点*/
            this.parent.add(this.keys[Math.floor(this.keys.length/2)]);
            /*自己保留右边*/
            this.keys = this.keys.slice(Math.floor(this.keys.length/2) + 1, this.keys.length);

            /*本节点的pages左边分配给左边,保留右边*/
            leftChild.pages =[].concat(this.pages.slice(0, Math.floor(this.pages.length/2)));
            this.pages = [].concat(this.pages.slice(Math.floor(this.pages.length/2), this.pages.length));
        }
    }
}

let btree = new BTree();
btree.addKey(53);
btree.addKey(75);
btree.addKey(139);
btree.addKey(49);
btree.addKey(145);
btree.addKey(36);
btree.addKey(101);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值