0

0

c++怎么实现线段树数据结构_c++ 区间查询与单点修改逻辑【指南】

尼克

尼克

发布时间:2025-12-26 14:02:38

|

467人浏览过

|

来源于php中文网

原创

线段树核心结构体采用数组式存储,tree大小为4*n,根节点编号为1,含n和tree成员;单点修改需递归定位叶子并回溯更新;区间查询须分无交、全含、部分重叠三种情况处理。

c++怎么实现线段树数据结构_c++ 区间查询与单点修改逻辑【指南】

线段树的核心结构体怎么写

线段树在 C++ 中最常用的是数组式(堆式)存储,而非指针式——因为避免动态分配开销、缓存友好、代码简洁。关键点是:tree 数组大小至少为 4 * nn 是原始数组长度),这是安全上界,能覆盖所有可能节点。

结构体里通常只存区间端点和值,不建议塞太多字段。例如支持「区间求和 + 单点修改」时,tree[i] 存的是对应区间的和:

struct SegmentTree {
    vector tree;
    int n;
SegmentTree(int size) : n(size), tree(4 * size, 0) {}

void build(const vectorzuojiankuohaophpcnintyoujiankuohaophpcn& arr, int node = 1, int l = 0, int r = -1) {
    if (r == -1) r = n - 1;
    if (l == r) {
        tree[node] = arr[l];
        return;
    }
    int mid = (l + r) / 2;
    build(arr, node * 2, l, mid);
    build(arr, node * 2 + 1, mid + 1, r);
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
}

};

注意:这里用 node * 2node * 2 + 1 表示左右子节点,根节点编号为 1(不是 0),这是标准堆式约定;若用 0 作根,则左子为 2*node+1,容易混淆,不推荐初学使用。

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

单点修改的递归逻辑怎么写才不出错

单点修改本质是「从根往下找唯一包含该位置的叶子,改完再向上更新父节点」。常见错误是边界判断写反、忘记回溯更新、或误把 l == r 当成递归终止但没处理好 mid 计算。

  • update(pos, val, node, l, r)pos 是原始数组下标(0-based),必须严格落在当前 [l, r]
  • 递归时只进一个分支:若 pos 走左,否则走右
  • 更新完子树后,一定要执行 tree[node] = tree[left] + tree[right],漏这步会导致查询结果错误

示例实现:

AI帮个忙
AI帮个忙

多功能AI小工具,帮你快速生成周报、日报、邮、简历等

下载
void update(int pos, long long val, int node = 1, int l = 0, int r = -1) {
    if (r == -1) r = n - 1;
    if (l == r) {
        tree[node] = val;
        return;
    }
    int mid = (l + r) / 2;
    if (pos <= mid) {
        update(pos, val, node * 2, l, mid);
    } else {
        update(pos, val, node * 2 + 1, mid + 1, r);
    }
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
}

区间查询为什么不能直接用 (l, r) 套公式

区间查询不是数学公式代入,而是递归拆解覆盖过程。典型错误是认为「只要当前节点区间被查询区间完全包含,就直接返回 tree[node]」,却忽略:若查询区间跨中点,必须拆成两段分别查,再合并结果。

正确逻辑分三种情况:

  • 当前区间 [l, r] 与查询区间 [ql, qr] 无交集 → 返回单位元(如求和返回 0
  • 当前区间被完全包含 → 直接返回 tree[node]
  • 部分重叠 → 递归查左右子树,返回二者之和

注意:边界比较必须用 ,不是 ;且查询函数应返回值,不是 void:

long long query(int ql, int qr, int node = 1, int l = 0, int r = -1) {
    if (r == -1) r = n - 1;
    if (qr < l || r < ql) return 0; // 无交集
    if (ql <= l && r <= qr) return tree[node]; // 完全包含
    int mid = (l + r) / 2;
    return query(ql, qr, node * 2, l, mid) +
           query(ql, qr, node * 2 + 1, mid + 1, r);
}

为什么 build / update / query 都要手动传参而不是封装成类成员方法

初学者常把 lr 提成类成员变量,结果发现多组查询会互相污染。根本原因是:线段树每个递归调用都依赖当前节点对应的区间范围,这个范围随调用深度变化,无法全局固定。

所以必须让 lr 作为参数层层传递。虽然看起来啰嗦,但这是最清晰、最不易出错的方式。C++17 后可用 std::optional 或默认参数简化接口(如上面示例用 r = -1 触发初始化),但底层逻辑不变。

另一个易忽略点:所有操作的时间复杂度都是 O(log n),但常数较大。如果只是做单点改 + 单点查,用普通数组就够了;只有真需要「任意区间求和/最小值/最大值」时,线段树才有意义。

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

193

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

184

2025.07.04

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

171

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

92

2025.11.27

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

529

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

2

2025.12.22

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

980

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

39

2025.10.17

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

25

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 6.5万人学习

前端基础到实战(HTML5+CSS3+ES6+NPM)
前端基础到实战(HTML5+CSS3+ES6+NPM)

共162课时 | 18.4万人学习

第二十二期_前端开发
第二十二期_前端开发

共119课时 | 12.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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