什麼是線段樹?有什麼用呢?
舉一個例子做簡單說明:
假設有一個數組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;
}
}
以後再慢慢更新線段樹的其他應用,等我找到好點的例題來講解