线段树
线段树 (Segment Tree ),简单理解就是将线段不断对折划分,直到其长度为1。对于线段树,感觉更像区间树,在原有上区间不断划分成新的子区间。
线段树节点
/**
* @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);
}