什么是线段树?有什么用呢?
举一个例子做简单说明:
假设有一个数组A,长度为N,对于这个数组,我有二种操作:第一是连续区间i到j的和,第二是修改某个索引i的值 ,在没有引入线段树以前,两个操作的时间复杂度分别是o(N)和o(1);
另外一种做法是:引入数组s,其中s[i]=a[0]+a[1]+……+a[i];不难看出,第一个查询操作的时间复杂度降到o(1),但是修改操作变成了o(N),那么有没有一种查询和修改时间平衡一点的做法呢?
于是引入线段树如图所示:
比如根节点的含义是:存储索引1~n的和,依次类推,对于上述的二个操作的时间复杂度均为log(N)
线段树Java实现
search和update方法分别对应查询和更新操作
public class SegmentTree {
Node root;
public SegmentTree(int left,int right){
root=buildTree(left,right);
}
public Node buildTree(int left,int right){
Node root=new Node(left,right);
if(right-left>=1){
int mid=(left+right)/2;
root.lchild=buildTree(left,mid);
root.rchild=buildTree(mid+1,right);
}
return root;
}
public int search(int left,int right){
return search(root,left,right);
}
private int search(Node node,int left,int right){
if(right>left) return 0;
if(node.left==left&&node.right==right) return node.val;
int mid=(left+right)/2;
return search(node.lchild,left,mid)+search(node.rchild,mid+1,right);
}
public void update(int index,int val){
update(root,index,val);
}
private int update(Node node,int index,int val){
if(node.right==node.left&&node.right==index){
node.val=val;
return node.val;
}else{
int mid=(node.left+node.right)/2;
if(index<=mid)
node.val=node.rchild.val+update(node.lchild,index,val);
else
node.val=node.lchild.val+update(node.rchild,index,val);
return node.val;
}
}
}
class Node{
int val; //存储 left~right的和
int left;
int right;
Node lchild;
Node rchild;
public Node(int left,int right){
this.left=left;
this.right=right;
val=0;
lchild=null;
rchild=null;
}
}
以后再慢慢更新线段树的其他应用,等我找到好点的例题来讲解