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

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

分段树(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);
    }
}
目录
相关文章
|
5天前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
80 64
|
2天前
|
机器学习/深度学习 存储 算法
【数据结构与算法基础】——算法复杂度
【数据结构与算法基础】——算法复杂度
|
6天前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
6天前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(三)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解
|
6天前
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(二)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解
|
6天前
|
存储
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(一)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解
|
6天前
|
机器学习/深度学习 存储 算法
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
【初阶数据结构】算法效率大揭秘 | 时间与空间复杂度的深度剖析
|
15天前
|
机器学习/深度学习 算法 Java
[算法与数据结构] 谈谈线性查找法~
该文章详细介绍了线性查找法的基本概念与实现方法,通过Java代码示例解释了如何在一个数组中查找特定元素,并分析了该算法的时间复杂度。
|
17天前
|
JSON 前端开发 JavaScript
一文了解树在前端中的应用,掌握数据结构中树的生命线
该文章详细介绍了树这一数据结构在前端开发中的应用,包括树的基本概念、遍历方法(如深度优先遍历、广度优先遍历)以及二叉树的先序、中序、后序遍历,并通过实例代码展示了如何在JavaScript中实现这些遍历算法。此外,文章还探讨了树结构在处理JSON数据时的应用场景。
一文了解树在前端中的应用,掌握数据结构中树的生命线
|
4天前
【数据结构】翻转、平衡、对称二叉树,最大深度、判断两棵树是否相等、另一棵树的子树
【数据结构】翻转、平衡、对称二叉树,最大深度、判断两棵树是否相等、另一棵树的子树
14 0