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

来源:互联网 发布:php addslashes和gpc 编辑:程序博客网 时间:2024/06/06 15:52

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

iterationidxposition of the last digitidx & -idxsum113 = 110101 (2 ^0)3212 = 110024 (2 ^2)1438 = 100038 (2 ^3)2640 = 0---------
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:
iterationidxposition of the last digitidx & -idx15 = 10101 (2 ^0)26 = 11012 (2 ^1)38 = 100038 (2 ^3)416 = 10000416 (2 ^4)532 = 100000------



与普通数组相比在查找时时间复杂度变成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

0 0
原创粉丝点击