树状数组

树状数组

定义

树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。

作用:

  • 实现求数组前缀和
  • 实现批量更新
  • 区间和快速查询(实质是两个端点前缀和相减得到)

下图为树状数组实现原理,红色箭头代表更新操作的执行顺序,绿色箭头代表查找操作的顺序

lowbit(x)就是求x最后一个1所代表的值,例如lowbit(9) = lowbit(1001) = 1
机器计算表达式为lowbit(x) = x & (-x),以12也就是1100为例:

计算机组成原理:
正数的原、反、补码都是其本身,负数的反码等于原码取反, 补码等于反码+1,计算都是通过补码进行

 x = 0 1100  (12)
原、反、补码都是01100,最前面的0为符号位
-x = 1 1100  (-12)
原码  1 1100   
反码  1 0011
补码  1 0100

x & ( - x ) = 01100 & 10100 = 00100
即取到了最后一位的值 100
let arr = [];
function lowbit(x) {
    return x & (-x);
}
/* 给index索引的结点+value */
function add(index, value) {
    while (index <= 16) {
        arr[index] = arr[index] == undefined ? value : (arr[index] + value);
        index += lowbit(index);
    }
}
/* 查询前缀和 */
function query(index) {/* 查询前缀和,结束位置为index */
    let sum = 0;
    while (index > 0) {
        sum += arr[index] == undefined ? 0 : arr[index];
        console.log(index, arr[index])
        index -= lowbit(index);
    }
    return sum;
}
/* 查询x~y区间 */
function getSum(x, y) {
    return query(y) - query(x - 1); 
}
原文地址:https://www.cnblogs.com/aeipyuan/p/12990179.html