• 封装线段树实现基本功能


    线段树封装

    1. 结点类TreeNode

    /* 树结点*/
    function TreeNode(x, y, val) {
        this.x = x;
        this.y = y;
        this.val = val || null;
    }
    

    2. 线段树类

    通过options可以传入pushUp函数设置父子结点关系,root记录线段树根节点

    function SegTree(options) {
        this.left = null;
        this.right = null;
        this.nums = options.nums;//数组
        this.pushUp = options.pushUp;//自定义父子关联的函数
        this.root = this.build(0, this.nums.length - 1);//建立线段树
    }
    

    3. 建树

    SegTree.prototype.build = function (x, y) {
        if (x === y) {/* 创建叶子结点并返回结点 */
            return new TreeNode(x, y, this.nums[x]);
        }
        /* 创建结点 */
        let node = new TreeNode(x, y);
        /* 创建子结点 */
        let mid = Math.floor(x + y >> 1);
        node.left = this.build(x, mid);
        node.right = this.build(mid + 1, y);
        /* 关联父子结点 */
        this.pushUp(node, node.left, node.right);
        return node;
    }
    

    4. 查询

    SegTree.prototype.query = function (tgtX, tgtY, node) {
        //默认为root
        node = node || this.root;
        let x = node.x, y = node.y;
        /* 在[tgtX,tgtY]区域内 */
        if (x >= tgtX && y <= tgtY) {
            return node.val;
        }
        /* 将查询到的值进行叠加 */
        let count = 0;
        let m = Math.floor(x + y >> 1);
        if (tgtY <= m)
            count += this.query(tgtX, tgtY, node.left);
        if (tgtX > m)
            count += this.query(tgtX, tgtY, node.right);
        return count;
    }
    

    5. 更新

    SegTree.prototype.update = function (tgtX, tgtY, val, node) {
        //默认为root
        node = node || this.root;
        if (node.x === node.y) {
            node.val += val;
            return;
        }
        let mid = Math.floor(tgtX + tgtY >> 1);
        if (tgtX <= mid)
            this.update(tgtX, tgtY, val, node.left)
        if (tgtY > mid)
            this.update(tgtX, tgtY, val, node.right);
        /* 更新父节点 */
        this.pushUp(node, node.left, node.right);
    }
    

    6. 删除

    SegTree.prototype.delete = function (tgtX, tgtY, node) {
        //默认为root
        node = node || this.root;
        if (tgtX >= node.x && tgtY <= node.y) {
            node.val = 0;
            return;
        }
        let mid = Math.floor(tgtX + tgtY >> 1);
        let flagx, flagy;//标识左右结点是否删除
        if (tgtX <= mid) {
            this.delete(tgtX, tgtY, node.left);
            flagx = true;
        }
        if (tgtY > mid) {
            this.delete(tgtX, tgtY, node.right);
            flagy = true;
        }
        /* 更新父节点 */
        this.pushUp(node, node.left, node.right);
        if (flagx) node.left = null;
        if (flagy) node.right = null;
    }
    

    测试代码

    /* 测试 */
    let tree = new SegTree({
        nums: [-2, 1, -3, 4, -1, 2, 1, -5, 4],
        pushUp: (node, xNode, yNode) => {
            node.val = xNode.val + yNode.val;
        }
    })
    console.log(tree.query(0, 8))//1
    tree.update(0, 8, 1)
    console.log(tree.query(0, 8))//10
    
  • 相关阅读:
    Dockerfile构建基础镜像为alpine的jdk1.8镜像
    app测试01_app测试漫谈
    ES基本操作命令
    springboot 前后端日期json格式化
    降维处理PCA
    分析鸢尾花数据集
    Python--matplotlib绘图可视化知识点整理
    模拟股票预期收益案例源代码
    np.random.normal()正态分布
    pandas
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/12990186.html
Copyright © 2020-2023  润新知