线段树的更新
SegmentTree.java
public void set(int index,E e){
if(index<0||index>=data.length)
throw new IllegalArgumentException("INDEX is illegal");
data[index]=e;
//更新tree
set(0,0,data.length-1,index,e);
}
//在以treeIndex 为根的线段树中更新 INDEX 的值为e
private void set (int treeIndex,int l,int r,int index,E e){
if(l==r&& l==index) {
tree[treeIndex]=e;
return ;
}
int TreeLeftIndex=leftChild(treeIndex);
int TreeRightIndex=rightChild(treeIndex);
int mid=l+(r-l)/2;
if(index<=mid)
set(TreeLeftIndex,l,mid,index,e );
else
set(TreeRightIndex,mid+1,r,index,e );
tree[treeIndex]=merger.merge(tree[TreeLeftIndex],tree[TreeRightIndex]);
}
线段树的完整框架
public class SegmentTree<E> {
private E[] tree;
private E[] data;
private Merger<E>merger;
public SegmentTree(E[] arr,Merger<E> merger){
this.merger=merger;
data=(E[])new Object[arr.length];
for(int i=0;i<arr.length;i++){
data[i]=arr[i];
}
//用数组表示树类型结构
tree=(E[])new Object[4*arr.length];
buildSegmentTree(0,0,data.length-1);//线段树的根结点索引为0
}
//递归构建索引为树结点treeindex 对应data区间[l,r]的信息
public void buildSegmentTree(int treeindex,int l,int r){
if(l==r){
tree[treeindex]=data[l];
return;
}
int treeleftchildindex=leftChild(treeindex);
int treerightchildindex=rightChild(treeindex);
int mid=l+(r-l)/2;
buildSegmentTree(treeleftchildindex,l,mid);
buildSegmentTree(treerightchildindex,mid+1,r);
// tree[treeindex]=+
tree[treeindex]=merger.merge(tree[treeleftchildindex],tree[treerightchildindex]);
}
public int getSize(){
return data.length;
}
public E get(int index){
if(index<0||index>=data.length)
throw new IllegalArgumentException("index is illeagal");
return data[index];
}
public int leftChild(int index){
return 2*index +1;
}
public int rightChild(int index){
return 2* index +2;
}
public E query(int queryL,int queryR){
if(queryL<0||queryL>=data.length||queryR<0||queryR>=data.length||queryL>queryR)
throw new IllegalArgumentException("index illegal");
return query(0,0,data.length-1,queryL,queryR);
}
//从线段树的treeIndex 索引开始在区间data[l:r]查找queryL,queryR 的值
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-l)/2;
if( queryR<=mid)
return query(leftChild(treeIndex),l,mid,queryL,queryR);
else if(queryL>=mid+1)
return query(rightChild(treeIndex),mid+1,r,queryL,queryR);
return merger.merge(query(leftChild(treeIndex),l,mid,queryL,mid),query(rightChild(treeIndex),mid+1,r,mid+1,queryR));}
public void set(int index,E e){
if(index<0||index>=data.length)
throw new IllegalArgumentException("INDEX is illegal");
data[index]=e;
//更新tree
set(0,0,data.length-1,index,e);
}
//在以treeIndex 为根的线段树中更新 INDEX 的值为e
private void set (int treeIndex,int l,int r,int index,E e){
if(l==r&& l==index) {
tree[treeIndex]=e;
return ;
}
int TreeLeftIndex=leftChild(treeIndex);
int TreeRightIndex=rightChild(treeIndex);
int mid=l+(r-l)/2;
if(index<=mid)
set(TreeLeftIndex,l,mid,index,e );
else
set(TreeRightIndex,mid+1,r,index,e );
tree[treeIndex]=merger.merge(tree[TreeLeftIndex],tree[TreeRightIndex]);
}
@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");
if(i!=tree.length-1) res.append(" ");
}
res.append(']');
return res.toString();
}
}
线段 树应用场景接口
Merge.java
public interface Merger<E> {
E merge(E a,E b);
}
线段树的调用
main.java
public class Main {
public static void main(String[] args) {
Integer[] nums={-2,0,3,-5,2,-1};
//匿名类
Merger<Integer> merger=new Merger<Integer>() {
@Override
public Integer merge(Integer a, Integer b) {
return a+b;
}
};
SegmentTree<Integer>segTree=new SegmentTree<>(nums,merger);
SegmentTree<Integer>segTree2=new SegmentTree<>(nums,(a,b)->a+b);//lambda 表达式
System.out.println(segTree.toString());
System.out.println(segTree.query(0,2));
// System.out.println(segTree.query(0,5));
}
}