Calmsym学习数据结构与算法之 树状数组(1)


前言

	今天我们继续学习维护区间的数据结构与算法;
在之前的学习中,我们学习了前缀和与差分,实现了如何维护区间和,以及区间查询,修改
	在前缀和与差分两中数据结构上,我们知道对于维护区间和的查询只需要O(1)
	但是对于单点或者区间修改的时间复杂度却是O(n)
	我们试图寻找一种结构,他对于两种维护的时间复杂度都尽可能少
	---树状数组

树状数组

什么是树状数组?

树状数组(BIT Binary Index Tree)所以树状数组的实质是二进制下标树,对于它的实现与二进制无法分割

为什么会与二进制扯上关系? 在前言中我们提到,我们尝试寻找一种结构使得他在维护一个数列是,无论是在 修改 还是 维护区间和 等的操作上,都尽可能地简便,缩短时间。

根据学习过的知识,我们很容易想到对于维护一个数列,我们可以另开数组去维护原数列,并将原数列分成一个个区间,单点修改时,只更新包含这一元素的区间;求前n项和时,通过将区间进行组合,得到从1到n的区间,然后对所有用到的区间求和

树状数组就是这样一种数据结构,它巧妙的利用二进制去划分区间,其维护的时间复杂度为O(logN)怎么实现,原理是什么我们娓娓道来

树状数组的原理和实现

根据 任意正整数关于2的不重复次幂的唯一分解性质
我们知道 若一个正整数 x 的二进制可以表示为 Ak-1 Ak-2 … A2 A1 A0
其中等于1的位是ai1ai2ai3…
所以 x 可以被分解成 x = 2 i 1 + 2 i 2 + . . . + x i m 所以 x 可以被分解成\\ x=2^{i1} + 2^{i2} +...+x^{im}\\ 所以x可以被分解成x=2i1+2i2+...+xim
不妨设 i1> i2 > i3 > … > im
那么区间【1,x】可以被分成O(logx)个小区间

这些小区间的共同特点是:若结尾为R,则区间长度就等于R的“二进制分解”下最小的2的次幂
即 lowbit(R)

例如
x = 7 = 2 2 + 2 1 + 2 0 区间 [ 1 , 7 ] 可以分成 [ 1 , 4 ] 、 [ 5 , 6 ] 、 [ 7 , 7 ] 三个小区间 长度分别为 l o w b i t ( 4 ) = 4 , l o w b i t ( 6 ) = 2 , l o w b i t ( 7 ) = 1 x=7 =2^2+2^1+2^0\\ 区间[ 1,7]可以分成[1,4]、[5,6]、[7,7]三个小区间\\ 长度分别为lowbit(4)=4, lowbit(6)=2, lowbit(7)=1 x=7=22+21+20区间[1,7]可以分成[1,4][5,6][7,7]三个小区间长度分别为lowbit(4)=4,lowbit(6)=2,lowbit(7)=1

什么是lowbit ?

lowbit(x) 即 取出非负整数 x 在二进制表示下最低位的 1 以及它后边 0 构成的数值
比如上面的 4 = 100 ,6 = 110 所以其最低为1与0组成的数分别为100与10
所以lowbit(4)= 4 ,lowbit(6)= 2

如何实现lowbit ?

l o w b i t ( x ) = ( x ) & ( − x ) lowbit(x)= (x) \And (-x) lowbit(x)=(x)&(x)
为什么可以这样?
我们需要知道,计算机里有符号数一般是以补码的形式存储的。
-x相当于x按位取反再加1,会把结尾处原来1000…的形式,变成0111…,再变成1000…;
而前面每一位都与原来相反。
这时我们再把它和x按位与,得到的结果便是lowbit(x)。
下面的图中举了两个例子:
在这里插入图片描述
知道了原理,接下来就是实现树状数组
我们会在(2)中展示树状数组的具体实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值