接口的代码在这里
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]);
}
}