线段树(java)

2023-11-13

线段树描述:
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为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() {

        }
        @Override
        public 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的当前节点的下标 初始值为1
       int 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的值改为5
        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));
    }
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线段树(java) 的相关文章

  • JavaMail Gmail 问题。 “准备启动 TLS”然后失败

    mailServerProperties System getProperties mailServerProperties put mail smtp port 587 mailServerProperties put mail smtp
  • 如何将 Java 赋值表达式转换为 Kotlin

    java中的一些东西就像 int a 1 b 2 c 1 if a b c System out print true 现在它应该转换为 kotlin 就像 var a Int 1 var b Int 2 var c Int 1 if a
  • 在Windows上安装Java 11 OpenJDK(系统路径问题)

    Java 11 最近发布了 众所周知 这个版本没有安装文件 当然 要在没有安装程序的情况下安装 Java 我将系统设置 PATH 和 JAVA HOME 设置为解压缩 Java 11 的文件夹的地址 根据对类似问题的已接受回复建议 唯一的事
  • 解决错误:日志已在具有多个实例的atomikos中使用

    我仅在使用atomikos的实时服务器上遇到问题 在我的本地服务器上它工作得很好 我在服务器上面临的问题是 init 中出错 日志已在使用中 完整的异常堆栈跟踪 java lang RuntimeException Log already
  • 如何查找 Android 设备中的所有文件并将它们放入列表中?

    我正在寻求帮助来列出 Android 外部存储设备中的所有文件 我想查找所有文件夹 包括主文件夹的子文件夹 有办法吗 我已经做了一个基本的工作 但我仍然没有得到想要的结果 这不起作用 这是我的代码 File files array file
  • 在数据流模板中调用 waitUntilFinish() 后可以运行代码吗?

    我有一个批处理 Apache Beam 作业 它从 GCS 获取文件作为输入 我的目标是根据执行后管道的状态将文件移动到两个 GCS 存储桶之一 如果管道执行成功 则将文件移动到存储桶 A 否则 如果管道在执行过程中出现任何未处理的异常 则
  • 使用 ANTLR 为 java 源代码生成抽象语法树

    如何使用 ANTLR 从 java src 代码生成 AST 有什么帮助吗 好的 步骤如下 前往ANTLR站点 http www antlr org 并下载最新版本 下载Java g和JavaTreeParser g文件来自here htt
  • HDFS:使用 Java / Scala API 移动多个文件

    我需要使用 Java Scala 程序移动 HDFS 中对应于给定正则表达式的多个文件 例如 我必须移动所有名称为 xml从文件夹a到文件夹b 使用 shell 命令我可以使用以下命令 bin hdfs dfs mv a xml b 我可以
  • jdbc4.MySQLSyntaxErrorException:数据库中不存在表

    我正在使用 SpringBoot 开发一个网络应用程序 这是我的application properties文件来指定访问数据库的凭据 spring datasource driverClassName com mysql jdbc Dri
  • 使用替换字符串中多个单词的最有效方法[重复]

    这个问题在这里已经有答案了 此刻我正在做 Example line replaceAll replaceAll cat dog replaceAll football rugby 我觉得那很丑 不确定有更好的方法吗 也许循环遍历哈希图 ED
  • 序列化对象以进行单元测试

    假设在单元测试中我需要一个对象 其中所有 50 个字段都设置了一些值 我不想手动设置所有这些字段 因为这需要时间而且很烦人 不知何故 我需要获得一个实例 其中所有字段都由一些非空值初始化 我有一个想法 如果我要调试一些代码 在某个时候我会得
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • 尝试使用 Ruby Java Bridge (RJB) gem 时出现错误“无法创建 Java VM”

    我正在尝试实现 Ruby Java Bridge RJB gem 来与 JVM 通信 以便我可以运行 Open NLP gem 我在 Windows 8 上安装并运行了 Java 所有迹象 至少我所知道的 都表明 Java 已安装并可运行
  • org.jdesktop.application 包不存在

    几天以来我一直在构建一个 Java 桌面应用程序 一切都很顺利 但是今天 当我打开Netbeans并编译文件时 出现以下编译错误 Compiling 9 source files to C Documents and Settings Ad
  • 使用 Flyway 和 Hibernate 的 hbm2ddl 在应用程序的生命周期中管理数据库模式

    我正在开发 Spring Hibernate MySql 应用程序 该应用程序尚未投入生产 我目前使用 Hibernatehbm2ddl该功能对于管理域上的更改非常方便 我也打算用Flyway用于数据库迁移 在未来的某个时候 该应用程序将首
  • 运行 Jar 文件时出现问题

    我已将 java 项目编译成 Jar 文件 但运行它时遇到问题 当我跑步时 java jar myJar jar 我收到以下错误 Could not find the main class myClass 类文件不在 jar 的根目录中 因
  • Java - 不要用 bufferedwriter 覆盖

    我有一个程序可以将人员添加到数组列表中 我想做的是将这些人也添加到文本文件中 但程序会覆盖第一行 因此这些人会被删除 如何告诉编译器在下一个空闲行写入 import java io import java util import javax
  • 如何配置eclipse以保持这种代码格式?

    以下代码来自 playframework 2 0 的示例 Display the dashboard public static Result index return ok dashboard render Project findInv
  • 中断连接套接字

    我有一个 GUI 其中包含要连接的服务器列表 如果用户单击服务器 则会连接到该服务器 如果用户单击第二个服务器 它将断开第一个服务器的连接并连接到第二个服务器 每个新连接都在一个新线程中运行 以便程序可以执行其他任务 但是 如果用户在第一个

随机推荐

  • 【MySQL】不就是多表查询综合练习

    前言 嗨咯大家好 我们学习完毕了多表查询 今天我们就要对我们所学的成果进行测验 本期主要是对多表查询相关内容的练习课程 可以先试着自己敲 遇到不会可以查看查考代码 目录 前言 目录 练习题 1 查询员工的姓名 年龄 职位 部门信息 隐式内连
  • 自学笔记-Python基础09--第三方库的概念及操作

    库 具有相关功能模块的集合 python的一大特色就是拥有强大的库 库可以分为三种 1 标准库 python自带的 无需安装直接使用 2 第三方库 由他人提供的 使用时需要先安装 3 自定义库 自己写的模块 自己用 标准库 想看python
  • react hooks 和 react-redux hooks 应用场景

    目前 Hooks 应该是 React 中最火的概念了 在阅读这篇文章之前 希望你已经了解了基本的 Hooks 是什么 下面就介绍一下简单的使用场景 react hooks useState useState是react自带的一个hook函数
  • 关于Spring的bean的相关注解以及其简单使用方法

    一 前置工作 第一步 创建一个maven项目 第二步 在resource中创建一个名字叫做spring config xml的文件 并把以下代码复制粘贴
  • 06——qt opengl 立方体 ebo 贴图

    qmyopenglwidget h ifndef QMYOPENGLWIDGET H define QMYOPENGLWIDGET H include
  • java中的泛型

    泛型 分为三种分别是泛型类 泛型方法 泛型接口 一 泛型类 直接在类名后面加上
  • 用C++流的方式读写文件

    一 代码 include
  • 【XSS漏洞-03】XSS漏洞语句构造和绕过方法实例

    目录 1 XSS语句构造方式 1 1 第一种 利用 lt gt 构造HTML JS语句 1 2 第二种 利用javascript 伪协议 1 3 第三种 事件驱动 1 4 第四种 利用CSS 层叠样式脚本 1 5 其他标签及手法 2 XSS
  • NFC模块方案,轻松实现NFC通讯

    一 主要特点 用户只需通过Uart串口控制就能实现NFC设备间数据传输 不需要了解NFC底层协议 迅速完成产品开发 二 支持平台 WinXP Win7 Win8 Win10 Linux Android 等等 三 NFC通讯控制模式 1 手机
  • decimal返回给前端是数字类型而不是字符串

    bigDecimal长度太长 返回给前端 精度会丢失 即后几位都会变成0 解决办法 给前端返回字符串类型 加注解 JsonSerialize using ToStringSerializer class 如果有些字段不要返回给前端呢 比如删
  • 循环神经网络学习笔记(基础篇)

    循环神经网络 RNN 基础篇学习笔记 一 权重共享 在CNN全连接层权重占比较多 在图像任务中 由于整个图像共享卷积核 所以实际参数量远远小于全连接层 在实际任务中 由于全连接层参数过多 我们需要使用RNN解决带有序列模式的数据 同时利用权
  • 各种排序方法的比较

    各种排序方法的比较 排序方法有很多 它们各有优缺点 没有绝对最好的和最坏的排序方法 只有最符合某个使用场景的方法 在选用排序方法的时候 我们应该综合考虑以下方面 1 时间复杂度 2 空间复杂度 3 稳定性 4 算法简单性 5 待排序记录个数
  • vscode 缩略图

    vscode 缩略图 缩略图的打开与关闭 快捷键 Ctrl Shift P 输入 minimap回车 每次为开启关闭交替 大段代码缩略图可以快速移动 分屏时关闭缩略图更好看
  • mysql复制数据表

    CREATE TABLE newtable LIKE oldtable INSERT newtable SELECT FROM oldtable
  • 解决问题记录4:kettle数据库连接报错时区问题

    问题 Connection failed Verify all connection parameters and confirm that the appropriate driver is installed The server ti
  • FastCGI介绍

    CGI Common Gateway Interface 公共网关接口 是HTTP服务器与其他程序通信的工具 FastCGI是一个long live型的CGI 支持分布式计算 它将CGI解释器进程保持在内存中并因此获得较高的性能 FastC
  • 多模态深度学习

    我们对世界的体验是多模态的 我们看到物体 听到声音 感受质地 闻到气味 然后做出决定 多模态学习表明 当我们的许多感官 视觉 听觉 动觉 参与信息处理时 我们理解和记忆更多 通过组合这些模态 学习者可以组合来自不同来源的信息 多模态深度学习
  • Yoga 14s电脑亮度不能调节?教你一招一下搞定。

    说一下背景 本人电脑联想yoga 14s 不知道最近那一天突然发现电脑亮度没法调节 写小论文时眼睛都要被刺瞎了 试了重装驱动 无果 升级系统 无果 最后河海大学的好朋友问了客服 客服一针见血问出 是否装过向日葵等远程软件 果然 我装了向日葵
  • 使用Python,matplotlib绘制复杂曲线,并求其交点,y=-sin(x)-x-1并求解函数的值

    写这篇博客源于博友的提问 将介绍如何使用Python matplotlib绘制复杂曲线 并求其交点 y sin x x 1并求解函数的值 1 效果图 y sin x 效果图如下 y x ln x 效果图如下 y sin x x 1 y 0
  • 线段树(java)

    线段树描述 线段树是一种二叉搜索树 与区间树相似 它将一个区间划分成一些单元区间 每个单元区间对应线段树中的一个叶结点 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数 时间复杂度为O logN 而未优化的空间复杂度为2N 实际应