美文网首页
BIT数据结构

BIT数据结构

作者: BinCode | 来源:发表于2018-04-04 10:48 被阅读0次

应用场景

定义数组array[n],求数组array[i]到array[j]的和(部分和)。在这种情况下,用一个简单的遍历可以解决问题,复杂度为O(n)。如果这种操作执行了m次,那么复杂度为O(mn),而树状数组可以把复杂度降至O(m*logn),适用于更新少但是部分和操作次数多的场景。

树状数组

树状数组(Binary Indexed Tree),本质就是一种通过二进制位来维护一个序列前i个和的数据结构,所以在其实更应该直白地翻译为二进制索引树。树状数组的索引都是以1开始,首先看一个例子。
设原始数组为a[8] = {3,4,5,6,7,8,9,2},那么树状数组e可以通过如下方式得到:
e[1] = a[1]
e[2] = a[1]+a[2]
e[3] = a[3]
e[4] = a[1]+a[2]+a[3]+a[4]=e[1]+e[2]+e[3]
e[5] = a[5]
e[6] = a[5]+a[6]
e[7] = a[7]
e[8] = a[1]+a[2]+...+a[8]
解释如下:

  1. 每一个树状数组元素都是一个或者多个原始数组的和。
  2. 如何确定当前树状数组是几个原始数组元素的和?
    将数组下标i表示为二进制,i从末尾开始连续0的个数定义为k。那么
e[i]=a[i-2^k +1]+a[i-2^k+2]+...+a[i]。

例如:e[8(1000)] = a[1]+a[2]+...+a[8]

后缀前缀

为了方便构造和使用树状数组,定义前缀和后缀两个操作。后缀一般在初始化和更新BIT数组中使用,前缀是为了求和的时候跳过重复的元素。

后缀

i的后缀为最为靠近i,且二进制末尾连续0的个数比i多的坐标。如e[2(10)]的后缀为e[4(100)],e[4(100)]的后缀为e[8(1000)]。后缀主要用来构造和更新树状数组
后缀的计算公式为:

//lowBit(i) = -i&i 或者 (i-1^i)&i 
//e[i]的后缀为e[i+low(i)]
int lowBit(int i){
  return -i&i;
}
构造树状数组

可以通过一次完整的扫描即可构造出树状数组,扫描的过程中每次去更新当前值的后缀即可。

 private void establishBIT() {
        for (int i = 1; i < orgin.length; i++) {
            if(i + lowBit(i)<orgin.length)
                bit[i + lowBit(i)] += bit[i];
        }
    }

如果其中某一项发生改变,只需要更新一下与之相关的后缀的值。

//更新操作
//结构内部以下标1作为数组的开始位
public void update(int pos, int num){
        if(pos<0||pos>orgin.length-1)
            return;
        int temp = orgin[pos+1];
        orgin[pos+1] = num;
        int delta = num-temp;
        pos = pos+1;
        while(pos<orgin.length){
            bit[pos]+=delta;
            pos = pos+lowBit(pos);
        }
    }

前缀

前缀的计算公式为:

//lowBit(i) = -i&i 或者 (i-1^i)&i 
//e[i] 的前缀为e[i-lowBit(i)]

前缀一般在求和的过程中会用到。

 public int sum(int p){
        int res= 0;
        while(p>0){
            res+=bit[p];
            p = p-lowBit(p);
        }
        return res;
    }

后缀是为了不重复计算元素,因为在BIT数组中每一项都是原始数组的一个或者多个的和。

源码

public class BIT {
    private int[] orgin;
    private int[] bit;

    public BIT(int[] inArray){
        orgin = new int[inArray.length+1];
        bit = new int[inArray.length+1];
        for(int i=1;i<inArray.length+1;i++){
            orgin[i] = inArray[i-1];
            bit[i] = inArray[i-1];
        }
        establishBIT();

    }

    private BIT(){}

    private void establishBIT() {
        for (int i = 1; i < orgin.length; i++) {
            if(i + lowBit(i)<orgin.length)
                bit[i + lowBit(i)] += bit[i];
        }
    }

    public String showBIT(){
        StringBuilder sb = new StringBuilder();
        for(int num : bit){
            sb.append(num);
            sb.append(" ");
        }
        return sb.toString();
    }

    private int lowBit(int i){
        return -i&i;
    }

    public void update(int pos, int num){
        if(pos<0||pos>orgin.length-1)
            return;
        int temp = orgin[pos+1];
        orgin[pos+1] = num;
        int delta = num-temp;
        pos = pos+1;
        while(pos<orgin.length){
            bit[pos]+=delta;
            pos = pos+lowBit(pos);
        }
    }

    public int sum(int p){
        int res= 0;
        while(p>0){
            res+=bit[p];
            p = p-lowBit(p);
        }
        return res;
    }
    public static void main(String[] args) {
        int[] input = new int[]{1,2,4,5,2,6,8,9};
        BIT bit = new BIT(input);
        System.out.println(bit.showBIT());
        System.out.println(bit.sum(1));
        bit.update(0,4);
        System.out.println(bit.showBIT());
    }
}

参考资料

https://www.cnblogs.com/grandyang/p/6657956.html
https://blog.csdn.net/u011567017/article/details/52252852
https://www.byvoid.com/zhs/blog/binary-index-tree

相关文章

  • BIT数据结构

    应用场景 定义数组array[n],求数组array[i]到array[j]的和(部分和)。在这种情况下,用一个简...

  • 2020 速递 Angular 和 React 背后的秘密(中)

    Bit fields(bit vectors) Bitfield 是比较底层的一种数据结构。可以理解为全部是由 0...

  • C语言中的位运算

    C语言中的位运算 结构体是唯一一种允许控制内存位(bit)的数据结构,称作位域(Bit Field) 位域不能离开...

  • [计概]第二章知识点

    速览 bit 1或0的一个符号单位, k个bit可以表示2k个不同状态编码 0和1的序列数据结构 编码方式+操作方...

  • 漫画:什么是布隆过滤器

    布隆过滤器的数据结构 布隆过滤器是一个 bit 向量或者说 bit 数组,长这样: 如果我们要把一个key映射到布...

  • C 迷你系列(四) 位域

    位域 位段(或称“位域”,Bit field)为一种 数据结构[https://zh.wikipedia.org/...

  • 常见数据结构

    参考文档数据结构中的树Bit-map空间压缩和快速排序去重浅谈算法和数据结构: 七 二叉查找树Java遍历树(深度...

  • Python数据结构实现Bitmap

    Bitmap bitmap是很常用的数据结构,比如用于Bloom Filter中;用于无重复整数的排序等等。bit...

  • python--集合set

    集合set是python基本的数据结构,是可变序列,无序不重复。 环境 win10 64bit python 3....

  • python--列表list

    列表list是python基本的数据结构,是可变序列,允许有重复元素。 环境 win10 64bit python...

网友评论

      本文标题:BIT数据结构

      本文链接:https://www.haomeiwen.com/subject/bhtxhftx.html