今天在刷leetcode时遇到了一道可以使用Binary Indexed Tree的题,以前未接触过,记下来以便以后复习
Binary Indexed Tree(树状数组)是一种树型数据结构,用于动态维护一个序列的前缀和。在实践中,它几乎总是用数组来实现;另外,由于代码易于记忆,它的树型结构很容易被忽略掉。它的中文名称“树状数组”很可能是因为以上两个特点得来。
低位(LowBit)
LowBit,即2进制数中从最低位开始连续0的位数的关于2的幂,其值LowBit(x)=x∧-x(x&-x,x and -x)。也就是上文所说的2^k
LowBit(x)显然就是not x中最低的是0的那一位,(not x)+1的那一位则会变成1,其更低的位全部变成0,而更高的位不变。由于更高的位就是原数取反,和原数求and的值为0,最低位就是唯一的是1的位了。所以LowBit(x)=x and((not x)+1)。 同时not x=-x-1,所以LowBit(x)=x and (-x)。
上图就是一个长度为16的数组的BIT,index(16)就表示落在16以内的个数,同时index(16)=sum(num[1]+num[2]+...+num[16])=index(8)+index(12)+index(14)+num[16]
即用index[i]表示从数据数组num中某一处一直到num[i]共2^k个元素的总和
读取累计的频率和
如果我们需要读取整数idx的频率累计和,我们可以让sum加上tree[idx]的值,然后让idx减去最有一个1(我们也可以说移走最后的1,使最后的1变为0),然后重复上述过程直至idx为0.我们可以使用下面这段
代码(C++)。
int read(int idx){
int sum = 0;
while (idx > 0){
sum += tree[idx];
idx -= (idx & -idx);
}
return sum;
}
举例: idx=13,sum=0: