首页 > 后端开发 > C++ > 正文

C++怎么实现一个二进制索引树(BIT)_C++数据结构与Fenwick树的高效实现

下次还敢
发布: 2025-11-23 19:43:02
原创
743人浏览过
二进制索引树(Fenwick树)通过lowbit操作实现O(log n)单点更新和前缀和查询,基于1-indexed数组,支持高效动态前缀和计算与区间和查询,适用于频繁更新与求和场景,代码简洁且性能优越。

c++怎么实现一个二进制索引树(bit)_c++数据结构与fenwick树的高效实现

二进制索引树(Binary Indexed Tree, BIT),也叫 Fenwick 树,是一种高效处理动态前缀和查询与单点更新的数据结构。它支持在 O(log n) 时间内完成单点修改和前缀和查询,实现简洁且常数小,特别适合频繁更新与查询的场景。

BIT 的基本原理

BIT 利用整数的二进制表示特性来组织数据。每个节点 tree[i] 存储从某个位置开始、长度为 i & (-i)(即 lowbit)的区间和。

关键操作是 lowbit(x),用于提取 x 的最低位 1 所代表的值:

int lowbit(int x) {
    return x & (-x);
}
登录后复制

例如:lowbit(6) = lowbit(110₂) = 10₂ = 2。

立即学习C++免费学习笔记(深入)”;

树的构建与操作实现

BIT 通常基于 1-indexed 数组实现,便于计算父节点与子节点关系。

1. 单点更新

将位置 i 的值增加 delta,并更新所有覆盖该位置的节点:

void update(int i, int delta) {
    while (i <= n) {
        tree[i] += delta;
        i += lowbit(i);
    }
}
登录后复制

2. 前缀和查询

计算从 1 到 i 的前缀和:

必应图像创建器
必应图像创建器

微软必应出品的AI绘图工具

必应图像创建器 593
查看详情 必应图像创建器
int prefix_sum(int i) {
    int sum = 0;
    while (i > 0) {
        sum += tree[i];
        i -= lowbit(i);
    }
    return sum;
}
登录后复制

3. 区间查询

区间 [l, r] 的和可通过前缀和相减得到:

int range_sum(int l, int r) {
    return prefix_sum(r) - prefix_sum(l - 1);
}
登录后复制

C++ 完整实现示例

下面是一个完整的 BIT 类封装:

#include <iostream>
#include <vector>
using namespace std;
<p>class FenwickTree {
private:
vector<int> tree;
int n;</p><pre class='brush:php;toolbar:false;'>int lowbit(int x) {
    return x & (-x);
}
登录后复制

public: FenwickTree(int size) { n = size; tree.assign(n + 1, 0); }

void update(int i, int delta) {
    while (i <= n) {
        tree[i] += delta;
        i += lowbit(i);
    }
}

int prefix_sum(int i) {
    int sum = 0;
    while (i > 0) {
        sum += tree[i];
        i -= lowbit(i);
    }
    return sum;
}

int range_sum(int l, int r) {
    return prefix_sum(r) - prefix_sum(l - 1);
}
登录后复制

};

// 使用示例 int main() { FenwickTree bit(5); bit.update(1, 10); bit.update(2, 20); bit.update(3, 30);

cout << "Sum [1,3]: " << bit.range_sum(1, 3) << endl; // 输出 60
cout << "Sum [2,4]: " << bit.range_sum(2, 4) << endl; // 输出 50

bit.update(2, 10); // 更新位置2 +10
cout << "Sum [1,3]: " << bit.range_sum(1, 3) << endl; // 输出 70

return 0;
登录后复制

}

应用场景与优势

BIT 适用于以下场景:

  • 动态数组的频繁前缀和查询
  • 逆序对计数(配合离散化)
  • 一维或多维差分更新与查询
  • 替代线段树在简单需求下的使用,代码更短,效率更高

相比线段树,BIT 实现更简单,内存占用更少,常数更小。虽然功能稍有限,但在只涉及单点更新+前缀查询时是首选。

基本上就这些。掌握 lowbit、update 和 prefix_sum 三个核心,就能灵活运用 BIT 解决很多问题。

以上就是C++怎么实现一个二进制索引树(BIT)_C++数据结构与Fenwick树的高效实现的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号