数据结构:java实现线段树

线段树

线段是是一种二叉搜索树,它将一段区间划分为若干单位区间,每一个结点都存储着一个区间,它功能强大,支持去捡求和、区间最大值。。。
1.定义一个接口,用来实现区间操作

package com.ff.数据结构.linesigntree;
//融合器
public interface Merger<E> {
     E merger(E num1,E num2);
}

2.构造线段树

public class LineSignTree<E>{
    E[] data; //存储的数据
    E[] treeData;  //存储整棵树的数据
    Merger<E> merger;
    LineSignTree(E[] data,Merger merger){
        this.data = data;
        this.merger = merger;
        //构造线段树
        //1.线段树的高度
        int height = (int) Math.ceil((Math.log(data.length))/Math.log(2)) + 1;
        //2.创建线段树的数组
        treeData = (E[])new Object[(int)Math.pow(2,height)-1];
        //3.构造线段树
        BuildLineSignTree(0,data.length-1,0);
    }

    private void BuildLineSignTree(int start,int end,int index){
        if(start == end){
            treeData[index] = data[start];
            return;
        }
        //左子树索引
        int leftIndex = index*2+1;
        //右子树索引
        int rightIndex = index*2+2;
        //中间结点
        int mid = start+(end - start)/2;
        //左子树
        BuildLineSignTree(start,mid,leftIndex);
        //右子树
        BuildLineSignTree(mid+1,end,rightIndex);
        //回溯相加
        treeData[index] = merger.merger(treeData[leftIndex],treeData[rightIndex]);
    }

    //对区间进行操作
    public E query(int start,int end,int index,int from,int to){
        if(start == from && end == to){
            return treeData[index];
        }
        //左子树索引
        int leftIndex = index*2+1;
        //右子树索引
        int rightIndex = index*2+2;
        //中间索引
        int midIndex = start + (end - start)/2;
        //查找的区间不在index结点所表示的区间内
        if(from > midIndex){
            return query(midIndex+1,end,rightIndex,from,to);
        }else if(to <= midIndex){
            return query(start,midIndex,leftIndex,from,to);
        }else {
            //跨区间
            return merger.merger(query(start,midIndex,leftIndex,from,midIndex),
                    query(midIndex+1,end,rightIndex,midIndex+1,to));
        }
    }

    public void update(int start,int end,int index,int oriIndex,E value){
        if(start == end){
            treeData[index] = data[oriIndex] = value;
            return;
        }
        //左子树索引
        int leftIndex = index*2+1;
        //右子树索引
        int rightIndex = index*2+2;
        //中间值
        int midIndex = start+(end-start)/2;
        if(oriIndex <= midIndex){
            update(start,midIndex,leftIndex,oriIndex,value);
        }else {
            update(midIndex+1,end,rightIndex,oriIndex,value);
        }
        treeData[index] = merger.merger(treeData[leftIndex],treeData[rightIndex]);

    }
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<treeData.length;i++){
            sb.append(treeData[i]);
            if(i!=treeData.length-1){
                sb.append(",");
            }
        }
        return sb.toString();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值