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

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

分段树(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);
    }
}
目录
相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
69 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
13天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
56 16
|
8天前
|
算法
树的遍历算法有哪些?
不同的遍历算法适用于不同的应用场景。深度优先搜索常用于搜索、路径查找等问题;广度优先搜索则在图的最短路径、层次相关的问题中较为常用;而二叉搜索树的遍历在数据排序、查找等方面有重要应用。
15 2
|
1月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
24 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
29天前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
32 4
|
1月前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
18 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
1月前
|
搜索推荐 算法
数据结构与算法学习十四:常用排序算法总结和对比
关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
19 0
数据结构与算法学习十四:常用排序算法总结和对比
|
1月前
|
Java C++
【数据结构】探索红黑树的奥秘:自平衡原理图解及与二叉查找树的比较
本文深入解析红黑树的自平衡原理,介绍其五大原则,并通过图解和代码示例展示其内部机制。同时,对比红黑树与二叉查找树的性能差异,帮助读者更好地理解这两种数据结构的特点和应用场景。
28 0
|
1月前
|
机器学习/深度学习 搜索推荐 算法
探索数据结构:初入算法之经典排序算法
探索数据结构:初入算法之经典排序算法