nodejs实现线段树

/**
 * 线段树
 * http://www.cnblogs.com/huangxincheng/archive/2012/12/08/2808207.html
 */
/**
 * 根据数组,以及数组的下标范围创建节点。
 */
let newNode = function(array,left,right){
    if(left == right){
        /*left,right节点中的max、min、sum是哪些元素的结果,通过数组的下标值表示*/
        return {
            left,
            right,
            max:array[left],
            min:array[left],
            sum:array[left]
        };
    }
    let mid = (left+right)/2;
    mid = mid|0;
    let leftChild = newNode(array,left,mid);
    let rightChild = newNode(array,mid+1,right);
    return {
        left,
        right,
        max:Math.max(leftChild.max,rightChild.max),
        min:Math.min(leftChild.min,rightChild.min),
        sum:leftChild.sum+rightChild.sum,
        leftChild,
        rightChild
    };
};
/**区间查询,查询某个范围的元素的max、min、sum*/
let query = function(node,left,right){
    if(left<=node.left && right>=node.right){
        return {
            max:node.max,
            sum:node.sum,
            min:node.min
        };
    }else{
        if(left>node.right || right<node.left){
            throw new Error();
        }
        let mid = ((node.left+node.right)/2)|0;
        if(left>mid){
            return query(node.rightChild,left,right);
        }else if(right<=mid){
            return query(node.leftChild,left,right);
        }else{
            let leftRes = query(node.leftChild,left,mid);
            let rightRes = query(node.rightChild,mid+1,right);
            return {
                max:Math.max(leftRes.max,rightRes.max),
                min:Math.min(leftRes.min,rightRes.min),
                sum:leftRes.sum+rightRes.sum
            };
        }
    }
};
/**更新值*/
let update = function(node,index,value){
    if(node.left == node.right){
        if(node.left == index){
            node.sum = value;
            node.max = value;
            node.min = value;
            return;
        }else{
            throw new Error();
        }
    }
    let mid = ((node.left+node.right)/2)|0;//按位或0,效果就是向下取整
    if(index<=mid){
        update(node.leftChild,index,value);
        node.max = Math.max(node.leftChild.max,node.max);
        node.min = Math.min(node.leftChild.min,node.min);
        node.sum = node.leftChild.sum + node.rightChild.sum;
    }else{
        update(node.rightChild,index,value);
        node.max = Math.max(node.rightChild.max,node.max);
        node.min = Math.min(node.rightChild.min,node.min);
        node.sum = node.leftChild.sum + node.rightChild.sum;
    }
};
let newLineSegTree = function(array){
    let root = newNode(array,0,array.length-1);
    root.query = function(left,right){
        if(left<root.left || right>root.right){
            throw new Error('给定的下标超出范围');
        }
        return query(root,left,right);
    };
    root.update = function(index,value){
        //实现类似python中arr[-1]可以指向最后一个元素的效果
        index = (index|0+array.length)%array.length;
        update(root,index,value);
    };
    return root;
};
function test(){
    let array = [2,5,4,9];
    let tree = newLineSegTree(array);
    //console.info(JSON.stringify(tree,null,2));
    let res = tree.query(1,1);
    //console.info(JSON.stringify(res,null,2));
    tree.update(2,6);
    console.info(JSON.stringify(tree,null,2));
}
test();

猜你喜欢

转载自blog.csdn.net/zhoujiaping123/article/details/80458552