Binary Indexed Tree(二进制索引树、树状数组)

今天在刷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)。

Binary Indexed Tree(二进制索引树、树状数组)_第1张图片

上图就是一个长度为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:

iteration idx position of the last digit idx & -idx sum
1 13 = 1101 0 1 (2 ^0) 3
2 12 = 1100 2 4 (2 ^2) 14
3 8 = 1000 3 8 (2 ^3) 26
4 0 = 0 --- --- ---
Binary Indexed Tree(二进制索引树、树状数组)_第2张图片
image 1.5 箭头指示了在遍历过程中使用的数据.

改变一些位置的频率并更新tree

当改变某些位置的频率时,所有tree中负责该位置的都需要更新。在读取idx的累计和时我们移走idx最后的1并且循环继续。修改tree中的一些值val时,我们需要增加当前idx的tree值tree[idx],增加idx最后一位的1(例如idx为6,该值增加了val,当tree[6]增加了val后。6的最后等于1的一位是2,所以6+2=8,需要继续修改tree[8]的值)并且循环继续之前的过程,只要idx小于MaxVal.C++写的函数如下
void update(int idx ,int val){
	while (idx <= MaxVal){
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
例如idx=5:
iteration idx position of the last digit idx & -idx
1 5 = 101 0 1 (2 ^0)
2 6 = 110 1 2 (2 ^1)
3 8 = 1000 3 8 (2 ^3)
4 16 = 10000 4 16 (2 ^4)
5 32 = 100000 --- ---


Binary Indexed Tree(二进制索引树、树状数组)_第3张图片

与普通数组相比在查找时时间复杂度变成logn,但增加了插入花销(普通数组插入复杂度为O(1),BIT为O(logn))

315. Count of Smaller Numbers After Self

题目为找出数组中每个数字后面比这个数小的数的个数

我们可以在将原数组排序后把问题变成每个数的索引在BIT中有多少比他小的索引,从左向右进行扫描,每扫描完成一个将其在BIT中的占位从BIT中减去,即可使用nlogn的复杂度完成任务。

315代码,搜索130


307. Range Sum Query - Mutable

题目要求求一个区间内数值的总和,是BIT的长项之一,直接构建BIT,将数组放到相应的索引内,区间值就是大索引的和减去小索引的和

307代码


相关链接:http://www.nocow.cn/index.php/%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84

    http://www.xuebuyuan.com/1396639.html

你可能感兴趣的:(算法)