经典算法:Fenwick Tree

1. 算法简介

Fenwick Tree又称为Binary Indexed Tree,也算是一种常见的数据结构了。

他其实某种意义上来说算是Segment Tree的一种变体,其主要的用途也是用于一些需要频繁对数组中元素进行变换以及范围内求和的数组的优化实现。

正如之前在Segment Tree的介绍博客(经典算法:Segment Tree)中说明的那样:数组的范围求和以及值更新事实上是两个比较难以兼顾的操作,往往在其中一个的时间复杂度是 O ( 1 ) O(1) O(1)时,另一个的时间复杂度就会变为 O ( N ) O(N) O(N)

因此,如果需要频繁地改变数组中的值以及对数组中某一范围内的元素进行求和或者其他操作的话,整体的时间复杂度就会变为 O ( N 2 ) O(N^2) O(N2)

而Segment Tree就是针对上述问题的一种解决方法,其核心思路是通过一个树结构来记录每一个分段当中元素的和/最大/最小值,从而使得元素的更新以及query的时间复杂度都退化为 O ( l o g N ) O(logN) O(logN),进而优化整体的算法复杂度为 O ( N l o g N ) O(NlogN) O(NlogN)

但是,如前述博客当中所述,Segment Tree实现所需的最小空间复杂度是 O ( 2 N ) O(2N) O(2N)

而基于这方面,Fenwick Tree,或者说Binary Indexed Tree则可以进一步地对这部分内容进行优化。

它同样可以使用一个数组来快速对其进行实现,且较之Segment Tree,它所需的空间复杂度仅为 O ( N ) O(N) O(N),且同样可以保持update以及query的单次时间复杂度为 O ( l o g N ) O(logN) O(logN)

但是,需要注意的是,在Segment Tree当中,任意一段区间都可以表示为树当中某一些子区间的合集,因此,我们可以任意变换来求取某一子区间的和/最大值/最小值,只要这个特征的计算是无序的,它总是可以用Segment Tree来实现的。

而在Fenwick Tree当中,我们却无法将任意子区间拆分为树上面某一些节点所表示的区间的合集。事实上,对于Fenwick Tree,我们只能够求得任意前 i i i个元素的特征。因此,对于求前序和或者求分段区间内和的问题,我们还是可以通过Fenwick Tree来替换实现的,但是如果要求得任意区间的最大值或者最小值时,Fenwick Tree就爱莫能助了……

综上,我们简单介绍了:

  1. Fenwick树是什么
  2. Fenwick树的主要用途
  3. 与Segment Tree相比较,Fenwick Tree的优点与缺点

下面,我们就来看一下Fenwick Tree的具体原理和实现。

2. 原理介绍

Fenwick Tree的原理,或者用它的另一个名字会更好理解一点,即Binary Indexed Tree。

本质上来说,它和Segment Tree的原理是接近的,都是通过将原数组进行切分,得到一系列小的区间,然后每次update和query操作时,就将两者都变成对于这些区间的操作,使得两者都变为 O ( l o g N ) O(logN) O(logN)的算法复杂度,而不会像传统的方法中那样一个是 O ( 1 ) O(1) O(1)和另一个是 O ( N ) O(N) O(N)

而具体的这个区分分割的方法就是Segment Tree和Fenwick Tree的唯一差别。

Segment Tree的方法直接trivial,就是通过二分法由顶向下地将原区间不断地拆分直到单元素。

而Fenwick Tree的思路则是相反的,它是由底向上地推过去,直到可以覆盖所有的数组区间。

具体来说,假设数组长度为 n n n,那么 n n n总可以用二进制进行表达,即: n = 2 i 1 + ⋯ 2 i k n = 2^{i_1} + \cdots 2^{i_k} n<

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值