线段树(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) 的相关文章

  • Java 中等效的并行扩展

    我在 Net 开发中使用并行扩展有一些经验 但我正在考虑在 Java 中做一些工作 这些工作将受益于易于使用的并行库 JVM 是否提供任何与并行扩展类似的工具 您应该熟悉java util concurrent http java sun
  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j
  • 使用 xpath 和 vtd-xml 以字符串形式获取元素的子节点和文本

    这是我的 XML 的一部分

随机推荐

  • 【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 实际应