【数据结构之树状数组】

转载 2015年07月11日 00:54:07
1、概述

树状数组(binary indexed tree),是一种设计新颖的数组结构,它能够高效地获取数组中连续n个数的和。概括说,树状数组通常用于解决以下问题:数组{a}中的元素可能不断地被修改,怎样才能快速地获取连续几个数的和?

2、树状数组基本操作

传统数组(共n个元素)的元素修改和连续元素求和的复杂度分别为O(1)和O(n)。树状数组通过将线性结构转换成伪树状结构(线性结构只能逐个扫描元素,而树状结构可以实现跳跃式扫描),使得修改和求和复杂度均为O(lgn),大大提高了整体效率。

给定序列(数列)A,我们设一个数组C满足

C[i] = A[i–2^k+ 1] + … + A[i]

其中,k为i在二进制下末尾0的个数,i从1开始算!

则我们称C为树状数组。

下面的问题是,给定i,如何求2^k?

答案很简单:2^k=i&(i^(i-1)) ,也就是i&(-i)

下面进行解释:

以i=6为例(注意:a_x表示数字a是x进制表示形式):

(i)_10 = (0110)_2

(i-1)_10=(0101)_2

i xor (i-1) =(0011)_2

i and (i xor (i-1))  =(0010)_2

2^k = 2

C[6] = C[6-2+1]+…+A[6]=A[5]+A[6]

数组C的具体含义如下图所示:

当我们修改A[i]的值时,可以从C[i]往根节点一路上溯,调整这条路上的所有C[]即可,这个操作的复杂度在最坏情况下就是树的高度即O(logn)。另外,对于求数列的前n项和,只需找到n以前的所有最大子树,把其根节点的C加起来即可。不难发现,这些子树的数目是n在二进制时1的个数,或者说是把n展开成2的幂方和时的项数,因此,求和操作的复杂度也是O(logn)。

树状数组能快速求任意区间的和:A[i] + A[i+1] + … + A[j],设sum(k) = A[1]+A[2]+…+A[k],则A[i] + A[i+1] + … + A[j] = sum(j)-sum(i-1)。

下面给出树状数组的C语言实现:

//求2^k
 
intlowbit(intt)
 
{
 
    returnt & ( t ^ ( t - 1 ) );
 
}
 
//求前n项和
 
intsum(intend)
 
{
 
   intsum = 0;
 
   while(end > 0)
 
  {
 
     sum += in[end];
 
     end -= lowbit(end);
 
  }
 
  returnsum;
 
}
 
//增加某个元素的大小
 
voidplus(intpos, intnum)
 
{
 
   while(pos <= n)
 
  {
 
     in[pos] += num;
 
     pos += lowbit(pos);
 
  }
 
}


3、扩展——二维树状数组

一维树状数组很容易扩展到二维,二维树状数组如下所示:

C[x][y] = sum(A[i][j])

其中,x-lowbit[x]+1 <= i<=x且y-lowbit[y]+1 <= j <=y

4、应用

(1)    一维树状数组:

参见:http://hi.baidu.com/lilu03555/blog/item/4118f04429739580b3b7dc74.html

(2)    二维树状数组:

一个由数字构成的大矩阵,能进行两种操作

1) 对矩阵里的某个数加上一个整数(可正可负)

2) 查询某个子矩阵里所有数字的和

要求对每次查询,输出结果

5、总结

树状数组最初是在设计压缩算法时发现的(见参考资料1),现在也会经常用语维护子序列和。它与线段树(具体见:数据结构之线段树)比较在思想上类似,比线段树节省空间且编程复杂度低,但使用范围比线段树小(如查询每个区间最小值问题)。

6、参考资料

(1)    Binary Indexed Trees:

http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees

(2)    吴豪文章《树状数组》:

http://www.java3z.com/cwbwebhome/article/article19/zip/treearray.zip

(3)    郭炜文章《线段树和树状数组》:

http://poj.org/summerschool/1_interval_tree.pdf

----------------------------------------------------------------------------------------------
更多关于数据结构和算法的介绍,请查看:数据结构与算法汇总
----------------------------------------------------------------------------------------------

原创文章,转载请注明: 转载自董的博客

本文链接地址: http://dongxicheng.org/structure/binary_indexed_tree/

作者:Dong,作者介绍:http://dongxicheng.org/about/

本博客的文章集合:


相关文章推荐

2017西安交大ACM小学期数据结构 [树状数组]

Problem C 发布时间: 2017年6月28日 11:38   最后更新: 2017年6月28日 16:38   时间限制: 1000ms   内存限制: 32M 描述 给定一个长度为...

2017西安交大ACM小学期数据结构 [树状数组,极大值]

Problem D 发布时间: 2017年6月28日 10:51   最后更新: 2017年6月28日 16:38   时间限制: 1000ms   内存限制: 32M 描述 给定一个长度为...

HDU 2642 Stars [二维树状数组]【数据结构】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2642—————————————————————————————–. StarsTime Limit:...

活用各种数据结构——RMQ/树状数组/分桶法和平方分割

对《挑战程序设计竞赛》的一个记录第三章 出类拔萃——中级篇上一篇:3.3活用各种数据结构——线段树篇3.3活用各种数据结构——RMQ/树状数组/分桶法和平方分割RMQ(区间最值查询)有一个长度为n的乱...

[数据结构]树状数组专辑

树状数组蛮简单的说~ 资料参考:百度百科讲的还是蛮清楚的 摘录一些重要的: 一般应用于数组求和, 数据更新。树状数组是一个查询和修改复杂度都为log(n)的数据结构比较:树状数组...
  • K2xbit
  • K2xbit
  • 2012年07月13日 23:43
  • 194

ACM-数据结构-树状数组I

ACM竞赛中,树状数组,即二分索引树(BinaryIndexedTree,BIT),也是常见的一种数据结构,其应用场景如下: 给出一个长度为n的数组(a[1]-a[n]),每一次给出一个i,询问该数组...

《挑战程序设计竞赛》3.3.1 数据结构-树状数组 POJ3468 1804 1990 3109 2155 2886(4)

# http://ac.jobdu.com/problem.php?pid=题意思路代码# http://ac.jobdu.com/problem.php?pid=题意思路代码# http://...

HDU 2838 Cow Sorting [树状数组]【数据结构】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2838 —————————————————-. Cow SortingTime Limit: 200...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【数据结构之树状数组】
举报原因:
原因补充:

(最多只允许输入30个字)