2021最新Java实现线段树(代码都有注释 容易看懂)

接口的代码在这里

public interface meige<E> {
    E meiger(E a, E b);
}

我的tostring写的很lj 所以tostring需要自己写哈 我这个只有自己看得懂

import java.util.Arrays;
//线段树底层也是数组 第一个值也就是根就是所有的值的总和(这个需要看自己的设定)我是这样设定的

public class sgementTree<E> {
    private E[] tree;
    private E[] data;
    private meige<E>m;
    public sgementTree (E[] arr, meige<E>m ){
        this.m=m;
        data=(E[]) new  Object[arr.length];//直接把数组的数据拷贝给data
        for(int i=0;i<arr.length;i++){
            data[i]=arr[i];
        }
        tree=(E[]) new  Object[arr.length*4];//这里要重点去理解为啥是*4 因为根据每一次的测试可知
        //如果数据为2的倍数 那么只要2n 但是它有可能为2n+1 那么则需要再多加一倍的量
        //所以直接用4倍更方便
        BuildsgemengTree(0,0,data.length-1);//这个表示从0为根开始,从0直到最后一个数结束

    }//在treeindex位置上来创建从l到r的线段树
    private void  BuildsgemengTree(int treeindex,int l,int r){
        if(l>=r){
            tree[treeindex]=data[r];//这个时候就随便了 l r都是可以的
            return;
        }
        int left=leftchild(treeindex);
        int right=rightchild(treeindex);
        int mid=(l+r)/2;
        //这个递归一定要看的懂  不看递归的话这个完成不了 最好是和2叉树,堆一起看 去寻找相同点和不同点
        BuildsgemengTree(left,l,mid);
        BuildsgemengTree(right,mid+1,r);
        tree[treeindex]=m.meiger(tree[left],tree[right]);


    }
    //这个方法是取从queryl到quertr的所有的值的和
    //是和的原因是因为自己设置的m.mege的那个方法为加 这个是可以自己变得 但是要理解这个递归为什么这么调用
    public E  query(int queryl,int quertr){
        return query(0,0,data.length-1,queryl,quertr);

    }                 //根         左边界  右边界   查找值的左边  查找值的右边
    private E query(int treeindex,int l,int r,int queryl,int queryr){
        //当递归进行到这样的时候 说明刚刚好 直接输出
        if(l==queryl&&r==queryr){
            return tree[treeindex];
        }
        int mid=(l+r/2);//这个在好多的地方都用到了
        int left=leftchild(treeindex);
        int right=rightchild(treeindex);
        //当要查找的值的左边大于中间的时候 说明直接可以去右边了  左边是啥也找不到的
        if(queryl>mid){
            return query(right,mid+1,r,queryl,queryr);
        }else if(queryr<=mid){
            return query(left,l,mid,queryl,queryr);
        }
        //下面的是正好左边有点   右边有点
        E leftc=query(left,l,mid,queryl,mid);
        E rightc=query(right,mid+1,r,mid+1,queryr);
        return m.meiger(leftc,rightc);
    }
    public int getsize(){
        return data.length;
    }
    public E get(int index){
        return data[index];
    }
    private int leftchild(int index){
        return 2*index+1;
    }
    private int rightchild(int index){
        return 2*index+2;
    }

    @Override
    public String toString() {
        StringBuilder res=new StringBuilder();
        res.append("[");
        for(int i=0;i<tree.length;i++){
            if(tree[i]!=null){
                res.append(tree[i]);
            }else{
                res.append("null");
            }
        }
        return res.toString();

    }
    //更新线段树 虽然我感觉用不上  但是干就完了
    public void set(int treeindex,int l,int r,int index,E e){
        if(l==r){
            tree[treeindex]=e;
            return;
        }
        int mid=(l+r)/2;
        int left=leftchild(treeindex);
        int right=rightchild(treeindex);
        if(index>mid){
            set(right,mid+1,r,index,e);

        }else{
            set(left,l,mid,index,e);
        }
        tree[treeindex]=m.meiger(tree[left],tree[right]);

    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值