线段树的粗糙理解

线段树

线段树 (Segment Tree ),简单理解就是将线段不断对折划分,直到其长度为1。对于线段树,感觉更像区间树,在原有上区间不断划分成新的子区间。

线段树.png

线段树节点


/**
 * @author 居無何
 * date: 2021/12/17 16:53
 * Description: 线段树的节点对象
 */
public class STNode {

    //存储的值
    public int val;

    //存储的左右区间
    public int star;
    public int end;

    //左右子节点
    public STNode left;
    public STNode right;

    public STNode() {
    }

    public STNode(int val, int star, int end, STNode left, STNode right) {
        this.val = val;
        this.star = star;
        this.end = end;
        this.left = left;
        this.right = right;
    }
    
}

线段树操作


/**
 * @author 居無何
 * date: 2021/12/17 16:57
 * Description: 线段树的相关操作
 */
public class SegmentTree {

    /**
     * 构建线段树
     * */
    public STNode createSegmentTree (int [] nums){
        return createSegmentTreeForRec(new STNode(),nums,0, nums.length-1);
    }

    /**
     * 递归创建线段树
     * */
    public STNode createSegmentTreeForRec (STNode stNode,int [] nums,int start,int end){
        //递归结束条件,当star==end时条件结束;并且start和end的范围合理。
        if (start==end) {
            stNode.val=nums[start];
            stNode.start=start;
            stNode.end=end;
            return stNode;
        }
        if (start>=end) return stNode;

        //对折划分
        int median = (start+end)/2;

        //标记
        stNode.start=start;
        stNode.end=end;

        //进入递归
        stNode.left=createSegmentTreeForRec(new STNode(),nums,start,median);
        stNode.right=createSegmentTreeForRec(new STNode(),nums,median+1,end);

        //比较左右子树,取出最大值
        stNode.val=Math.max(stNode.left.val,stNode.right.val);

        return stNode;
    }

    /**
     * 更新线段树的值
     * */
    public void updateSegmentTree (STNode stNode,int index,int val){

        //当index不在范围中
        if (index> stNode.end || index< stNode.start){
            return;
        }

        //索引index与start相同时,更新数据
        if (stNode.start==index && stNode.end==index){
            stNode.val=val;
            return;
        }

        int median = (stNode.start+stNode.end)/2;

        //进行递归,判断索引在那段位置
        if (index<=median && median>=0){
            updateSegmentTree(stNode.left,index,val);
            stNode.val=Math.max(stNode.left.val,stNode.right.val);
            return;
        }
        updateSegmentTree(stNode.right,index,val);
        stNode.val=Math.max(stNode.left.val,stNode.right.val);

    }

    /**
     * 求整个线段树的元素之和
     * */
    public int sumSegmentTree(STNode stNode,int sum) {

        //递归结束条件
        if (stNode.start==stNode.end){
            sum+=stNode.val;
            return sum;
        }

        //进行递归
        sum=sumSegmentTree(stNode.left,sum);
        sum=sumSegmentTree(stNode.right,sum);

        return sum;
    }

    public void selectSegmentTree (STNode stNode){
        if (stNode.left==stNode.right){
            System.out.println(stNode.val);
            return;
        }

       selectSegmentTree(stNode.left);
        selectSegmentTree(stNode.right);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值