数据结构和算法--分段树

简介: 数据结构和算法--分段树

分段树(Segment Tree)是一种高级数据结构,源于计算机科学领域,特别适用于解决与区间相关的动态查询和更新问题。分段树本质上是一种二叉树结构,但它并不是典型的完全二叉树或满二叉树,而是通过对输入数组进行分段并构建树形结构来实现高效的区间操作。

分段树的基本概念:

定义: 分段树主要应用于一个数组或序列中,用于快速查询和更新指定区间内的某个特定属性,如区间和、区间最大值、区间最小值等。每个节点代表一个区间,并且这个区间是其左右子节点区间的合并。

构造过程:

输入是一组数据,通常是一个数组A[0...n-1]。

将整个数组看作一个区间,构造一个包含2^n - 1个节点的树(因此,对于n个元素的数组,树的高度大致为log_2(n))。

树的每个内部节点覆盖两个子区间,它们分别由该节点的左右子节点表示,而叶子节点恰好对应数组的一个单元格。

节点信息:

每个节点不仅存储它所覆盖区间的边界,还存储了一个摘要信息,例如该区间的和、最大值、最小值或其他根据问题需求计算得到的聚合信息。

操作支持:

查询操作:给定一个查询区间,可以在O(log n)时间内找到该区间内的目标信息,如区间和或区间最大值。

更新操作:当数组中的某个元素值发生改变时,可以在O(log n)时间内重新计算受影响的所有区间信息。

实例:

对于一个数值型数组,如果我们想要支持快速查询任意连续子数组的和,那么分段树的每个节点会存储它所管辖的子数组之和。

如果我们关注区间最大值,则每个节点存储其子区间内的最大值。

分段树的实现细节:

在Java或C++等编程语言中,分段树经常通过一个数组实现,而不是实际的二叉树结构。这是因为虽然逻辑上是二叉树,但在内存中我们可以利用数组的连续性减少指针引用的成本。数组的下标与树的层级和位置之间存在一定的转换规则,以便快速定位到相应区间对应的节点。

Java代码展示如何构建一个分段树来维护数组区间和的问题:

public class SegmentTree {
    private int[] tree;
    private int n;

    // 构造函数,传入原始数组arr,构建分段树
    public SegmentTree(int[] arr) {
        n = arr.length;
        tree = new int[n * 2]; // 由于每个节点都会存储信息,所以初始化的空间是原数组的两倍
        build(arr, 0, 0, n - 1); // 递归构建分段树
    }

    // 递归构建分段树
    private void build(int[] arr, int node, int start, int end) {
        if(start == end) {
            // 叶子节点,直接赋值
            tree[node] = arr[start];
        } else {
            // 内部节点,计算左右子区间和
            int mid = start + (end - start) / 2;
            build(arr, 2 * node + 1, start, mid);
            build(arr, 2 * node + 2, mid + 1, end);
            // 合并子区间信息
            tree[node] = tree[2 * node + 1] + tree[2 * node + 2];
        }
    }

    // 区间更新函数,更新区间 [i, j] 的所有元素增加 val
    public void update(int i, int j, int val) {
        updateHelper(i, j, val, 0, 0, n - 1);
    }

    private void updateHelper(int i, int j, int val, int node, int start, int end) {
        if (i > end || j < start) return; // 区间不重叠,直接返回
        if (start >= i && end <= j) { // 区间完全包含在[i, j]内
            tree[node] += (end - start + 1) * val; // 更新节点值
            if (start != end) { // 如果不是叶子节点,还需递归更新子节点
                updateHelper(i, j, val, 2 * node + 1, start, (start + end) / 2);
                updateHelper(i, j, val, 2 * node + 2, (start + end) / 2 + 1, end);
            }
        } else { // 区间部分重叠
            updateHelper(i, j, val, 2 * node + 1, start, (start + end) / 2);
            updateHelper(i, j, val, 2 * node + 2, (start + end) / 2 + 1, end);
            tree[node] = tree[2 * node + 1] + tree[2 * node + 2]; // 重新计算节点值
        }
    }

    // 查询区间 [queryStart, queryEnd] 的和
    public int query(int queryStart, int queryEnd) {
        return queryHelper(queryStart, queryEnd, 0, 0, n - 1);
    }

    private int queryHelper(int queryStart, int queryEnd, int node, int start, int end) {
        if (queryStart > end || queryEnd < start) return 0; // 区间不重叠
        if (queryStart <= start && queryEnd >= end) return tree[node]; // 区间完全包含在查询区间内
        int mid = start + (end - start) / 2;
        return queryHelper(queryStart, queryEnd, 2 * node + 1, start, mid) +
               queryHelper(queryStart, queryEnd, 2 * node + 2, mid + 1, end);
    }
}
目录
相关文章
|
4月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
112 1
|
1月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
86 29
|
1月前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
94 25
|
1月前
|
存储 人工智能 算法
C 408—《数据结构》算法题基础篇—数组(通俗易懂)
408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
72 23
|
2月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
68 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
2月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
59 12
|
2月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
53 10
|
3月前
|
存储 运维 监控
探索局域网电脑监控软件:Python算法与数据结构的巧妙结合
在数字化时代,局域网电脑监控软件成为企业管理和IT运维的重要工具,确保数据安全和网络稳定。本文探讨其背后的关键技术——Python中的算法与数据结构,如字典用于高效存储设备信息,以及数据收集、异常检测和聚合算法提升监控效率。通过Python代码示例,展示了如何实现基本监控功能,帮助读者理解其工作原理并激发技术兴趣。
84 20
|
2月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
55 2
|
4月前
|
存储 算法 搜索推荐
Python 中数据结构和算法的关系
数据结构是算法的载体,算法是对数据结构的操作和运用。它们共同构成了计算机程序的核心,对于提高程序的质量和性能具有至关重要的作用
116 33