线段树(java)

article/2025/9/30 1:19:24

线段树描述:
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。
例图如下:
在这里插入图片描述
代码实现如下:主要实现了线段树的构建,单点更新、区间和、最大值和一些测试用例

import java.util.Scanner;
public class Xds {//线段树的实现    我们都是默认从下标为1开始的  编号寻找为左节点2*i  右节点为2*i+//线段树节点(用于建立线段树节点对象数组)static class Tree{int left;//记录当前节点左边界int right;//记录当前节点又边界int max;//记录当前节点的最大值int sum;//记录当前节点的所有和public Tree() {}@Overridepublic String toString() {return "Tree{" +"left=" + left +", right=" + right +", max=" + max +", sum=" + sum +'}';}}//构建线段树public static void build(int u,int left,int right,int[] a,Tree[] trees){//建立线段树函数   u表示当前节点的编号 a表示要建立线段树的原数组trees[u].left=left;//当前节点的左边界trees[u].right=right;//当前节点的又边界if(left==right){//表示到达了叶子节点trees[u].max=a[left];trees[u].sum=a[left];return;}else {int mid = (left + right) >>1;//计算中点的坐标build(2 * u, left, mid, a, trees);//递归解决所有节点信息build(2 * u + 1, mid + 1, right, a, trees);trees[u].max = Math.max(trees[2 * u].max, trees[2 * u + 1].max);//记录当前节点的最大值trees[u].sum=trees[2*u].sum+trees[2*u+1].sum;//记录当前节点的left和right之间的sum和}}//查找线段树指定范围之间的最大值public static int getMax(int left,int right,Tree[] trees,int u){//u表示当前节点的位置int mid=(trees[u].left+trees[u].right)>>1;//递归出口  到达叶子节点或者左右节点包含的情况下if (trees[u].left==trees[u].right||(left<=trees[u].left&&right>=trees[u].right)) return trees[u].max;if(right<=mid){//如果右边界小于中点的标号,则走左边界return getMax(left,right,trees,2*u);}else if (left>mid){//如果左边界大于中点的标号,则走右边界return getMax(left,right,trees,2*u+1);}else {int temp=getMax(left,mid,trees,2*u);//找到左边的最值int temp1=getMax(mid+1,right,trees,2*u+1);//找到右边的最值return Math.max(temp,temp1);}}//查找线段树指定范围之间的所有和public static int getSum(int left,int right,Tree[] trees,int u){int mid=(trees[u].left+trees[u].right)>>1;//递归出口  到达叶子节点或者左右节点对应相等的情况下if (trees[u].left==trees[u].right||(left==trees[u].left&&right==trees[u].right)) return trees[u].sum;if(right<=mid){//如果右边界小于中点的标号,则走左边界return getSum(left,right,trees,2*u);}else if (left>mid){//如果左边界大于中点的标号,则走右边界return getSum(left,right,trees,2*u+1);}else {int temp=getSum(left,mid,trees,2*u);//找到左边的所有和int temp1=getSum(mid+1,right,trees,2*u+1);//找到右边的所有和return temp+temp1;}}//寻找下标为index的元素在trees中的下标public static int getIndex(int index,Tree[] trees,int u){ //u表示trees的当前节点的下标 初始值为1//递归出口if (trees[u].left==index&&trees[u].right==index){//左右边界值相等return u;//返回在trees数组中的下标}int left=trees[u].left;//找到当前节点左边界int right=trees[u].right;//找到当前节点的有边界int mid=(left+right)>>1;if (index<=mid){//找到左边边界return getIndex(index,trees,2*u);}else return getIndex(index,trees,2*u+1);}//修改线段树内容(点更新)public static void update(int index,int value,Tree[] trees,int u){//将下标为index的值转换为value  u表示trees的当前节点的下标 初始值为1int i=getIndex(index,trees,u);//找到index的对应trees数组中的下标trees[i].max=value;//更新其叶子节点的max和value值trees[i].sum=value;i=i>>1;while (i>=u){//若i变为根节点的编号u,则退出循环 向上回溯解决修改节点值trees[i].max=Math.max(trees[2*i].max,trees[2*i+1].max);trees[i].sum=trees[2*i].sum+trees[2*i+1].sum;i=i>>1;}}//测试public static void main(String[] args) {Scanner scanner=new Scanner(System.in);int n=scanner.nextInt();//输入数组的大小int[] a=new int[n+1];for (int i = 1; i <=n ; i++) {a[i]=scanner.nextInt();}Tree[] trees=new Tree[4*n];//空间开4倍的数组长度大小for (int i = 0; i <4*n ; i++) {//防止空指针 所以需要每个都进行初始化trees[i]=new Tree();}build(1,1,n,a,trees);for (int i = 1; i <4*n ; i++) {System.out.println(trees[i].toString());}System.out.println("index "+getIndex(2,trees,1));System.out.println("max "+getMax(1,3,trees,1));System.out.println("sum "+getSum(1,4,trees,1));update(2,5,trees,1);//将元素组a的下标为2的值改为5for (int i = 1; i <4*n ; i++) {System.out.println(trees[i].toString());}System.out.println("index "+getIndex(2,trees,1));System.out.println("max "+getMax(1,3,trees,1));System.out.println("sum "+getSum(1,4,trees,1));}
}

运行结果如下:
在这里插入图片描述
在这里插入图片描述


http://chatgpt.dhexx.cn/article/snTjxlWD.shtml

相关文章

什么是线段树

线段树的概念 线段树是一种二叉搜索树&#xff0c;与区间树相似&#xff0c;它将一个区间划分成一些单元区间&#xff0c;每个单元区间对应线段树中的一个叶结点。 对于线段树中的每一个非叶子节点[a,b]&#xff0c;它的左儿子表示的区间为[a,(ab)/2]&#xff0c;右儿…

李超线段树

什么是李超线段树 先以一个问题引入&#xff1a; 在平面上有两种操作&#xff08;强制在线&#xff09;&#xff1a; 插入一条表达式为 L : y k*xb 的直线&#xff0c;给出 k ,b 。 给出 t&#xff0c;求当前所有直线中与直线 x t 交点的纵坐标最大是多少 直线取 max 应该是…

线段树详解 (原理,实现与应用)

线段树详解 By 岩之痕 目录&#xff1a; 一&#xff1a;综述 二&#xff1a;原理 三&#xff1a;递归实现 四&#xff1a;非递归原理 五&#xff1a;非递归实现 六&#xff1a;线段树解题模型 七&#xff1a;扫描线 八&#xff1a;可持久化 (主席树) 九&#xff1a;练习题 一&a…

线段树详解(附图解,模板及经典例题分析)

1.基本概念 ​ 线段树是一种常用来维护 区间信息 \color{Maroon}区间信息 区间信息 的数据结构 ​ 可以在 O(logn) 的时间复杂度内实现单点修改、区间修改、区间查询&#xff08;区间求和&#xff0c;求区间的最大值&#xff0c;求区间的最小值&#xff09;等操作 ​ 如下图…

线段树详解

文章目录 1. 什么是线段树2. 线段树的用处3. 线段树的模板题4. 动态开点线段树5. 权值线段树5. 可持久化线段树 1. 什么是线段树 顾名思义 &#xff0c; 线段树是一棵二叉树 &#xff0c; 但不同的是这棵树的结点储存的值是一个数列中 [ l , r ] [l,r] [l,r] 的某个需要的值 …

超详解线段树(浅显易懂,几乎涵盖所有线段树类型讲解,匠心之作,图文并茂)

一&#xff0c;什么是线段树&#xff1f; 线段树是怎样的树形结构? 线段树是一种二叉搜索树&#xff0c;而二叉搜索树&#xff0c;首先满足二叉树&#xff0c;即每个结点最多有两颗子树&#xff0c;并且是一颗搜索树&#xff0c;我们要知道&#xff0c;线段树的每个结点都存储…

线段树 从入门到进阶(超清晰,简单易懂)

目录 第一部 概念引入第二部 简单&#xff08;无pushdown&#xff09;的线段树1、单点修改&#xff0c;区间查询2、区间修改&#xff0c;单点查询 第三部 进阶线段树第四部 乘法&#xff08;根号&#xff09;线段树1、乘法线段树2、根号线段树模板题与代码&#xff1a;单点修改…

Navicat Premium 数据库开发工具

官网地址&#xff1a;https://www.navicat.com.cn/ Navicat Premium 是一套数据库开发工具&#xff0c;让你从单一应用程序中同时连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 数据库。它与 Amazon RDS、Amazon Aurora、Amazon Redshift、Microso…

Navicat 一款数据库开发软件

Navicat premium是一款数据库管理工具&#xff0c;非常好用&#xff0c;能复制表结构等&#xff0c;大大简化了后端开发的工程量&#xff0c;其软件示意图如下 Navicat Premium 15 已经发布了&#xff0c;但是价格昂贵&#xff0c;所以将 no-money version 的双手奉上。 使用…

Java学习中的数据库和数据库开发工具

一、数据库 1、数据库&#xff0c;通常是一个戒一组文件&#xff0c;保存了一些符合特定规格的数据&#xff0c;数据库对应的英询单词是DataBase&#xff0c;简称DB&#xff1b;数据库软件称为数据库管理系统&#xff0c;英文简称DBMS&#xff0c;全称为DataBase Management S…

五大主流数据库深度对比!数据库开发、管理看这篇就够了

开发数据库应用&#xff0c;选择一个好的数据库是非常重要的。目前&#xff0c;商品化的数据库管理系统以关系型数据库为主导产品&#xff0c; 技术比较成熟。面向对象的数据库管理系统技术先进&#xff0c;数据库易于开发、维护。无论是关系型数据库还是非关系型数据库&#x…

mysql数据库开发环境_MySQL数据库教程-环境与集成开发工具

MySQL数据库基础教程 数据库是存储数据与管理数据的基础,也是目前绝大多数动态网站开发所必备的基础知识。MySQL数据库教程系列文章主要以MySQL数据库管理系统为例对关系型数据库相关定义与操作等进行讲解。并结合php与PDO等讲解,为初学者提供快速学习PHP动态网站开发所需的知…

C/C++ MySQL数据库开发

C/C++ MySQL数据库开发笔记 MySQL启动方式手动启动MySQL数据库:命令行方式启动MySQL数据库:配置环境变量MySQL在Linux下安装MySQL的配置文件重要参数设置C/C++ 访问MySQL数据库(MySQL开发环境的配置(MySQL开发头文件和库文件)MySQL 数据库的连接MySQL 数据类型以及对应的 …

1、 数据库开发规范

第1章 数据库开发规范的制定 数据库设计步骤&#xff1a; 1、数据结构设计&#xff1a;逻辑设计-》物理设计 2、实际工作中&#xff1a;逻辑设计物理设计 3、物理设计&#xff1a;表名字段名字段类型 数据库设计几个规范&#xff1a; 数据库命名规范、数据库基本设计规范…

数据库开发-2-开发数据库的要点

Lec2-开发数据库的要点 1. 开发成功数据库应用的特点 需要理解数据库体系结构需要理解锁和并发控制特性&#xff1a;每个数据库都以不同的方式实现最重要的是不要把数据库当"黑盒" 要了解每一个数据库的体系结构和特征最常见的问题就是因为我们对数据库本身了解不足…

数据库开发(Sqlite)

1、数据库开发 1.1 数据与数据管理 什么是信息&#xff1f;   信息是指对现实世界存在方式或运动状态的反应。 什么是数据&#xff1f;   数据是指存储在某一媒体上&#xff0c;能够被识别的物理符号&#xff1b;   数据的概念在数据处理领域已经被大为拓宽&#xff0c…

《软件测试的艺术》第4章:测试用例的设计-白盒测试

写在前面&#xff1a;原书中包含白盒测试、黑盒测试、错误猜测、测试策略四个小节&#xff0c;涵盖内容较多&#xff0c;因此按章节拆分叙述。 《软件测试的艺术》&#xff1a; 白盒测试--语句覆盖 语句覆盖的用例设计原则&#xff1a;将程序中的每条语句至少执行一次。 白盒…

《软件测试的艺术》读后感 Or 读书笔记

《软件测试的艺术》读后感 Or 读书笔记 第一章 一次自评价测试第二章 软件测试的心理学和经济学第三章 代码检查、走查与评审第四章 测试用例的设计第五章 模块&#xff08;单元&#xff09;测试第六章 更高级别的测试第七章 可用性&#xff08;或用户体验&#xff09;测试第八…

软件测试的艺术 学习笔记

文章目录 4.2黑盒测试4.2.1 等价划分4.2.2 边界值分析4.2.3 因果图 4.3 错误猜测4.4 测试策略 5. 模块(单元&#xff09;测试5.1 测试用例设计5.2 增量测试5.3 自顶向下测试与自底向上测试5.3.1 自顶向下的测试5.3.2 自底向上的测试5.3.3 比较 5.4 执行测试 6 更高级别的测试6.…

《软件测试的艺术》第六章 更高级别的测试

《软件测试的艺术》第六章 更高级别的测试 6.0 前言软件开发过程模型 6.1 功能测试6.2 系统测试6.2.1 能力测试6.2.2 容量测试6.2.3 强度测试6.2.4 可用性测试6.2.5 安全性测试6.2.6 性能测试6.2.7 存储测试6.2.8 配置设置6.2.9 兼容性/转换测试6.2.10 安装测试6.2.11 可靠性测…