线段树 (真正的二叉树版 擅长二叉树与指针的人可以看我修改的版本,是在网上的数组版本上修改的)采用malloc动态申请内存的方式逐个节点的去创建二叉树,其本质与通过指针创建二叉树的方式大致相同
本章的代码目前网上似乎还没有,或者有但是不流行,我找到的都是纯数组或结构体数组版,开销较大.
结构体如下所示,显然与数据结构中的二叉树节点采用的是同种方式
为方便书写,我用typedef将指向该节点的指针类型定义成了SegTree,类似于陈越版数据结构中二叉树里的BinTree
typedef struct SegNode{
int l,r;
int sum;
SegNode* left;
SegNode* right;
}* SegTree;
之后是递归创建线段树
SegTree buildSegTree(int l,int r,int target[]){
SegTree ST=NULL;
ST=(SegTree)malloc(sizeof(struct SegNode));
ST->left=ST->right=NULL;
ST->l=l;
ST->r=r;
if(l==r){
ST->sum=target[l];
return ST;
}
int mid=(l+r)/2;
SegTree left=buildSegTree(l,mid,target);
SegTree right=buildSegTree(mid+1,r,target);
ST->left=left;
ST->right=right;
ST->sum=left->sum+right->sum;
return ST;
}
查询线段树
int query(SegTree ST,int x,int y){
int l=ST->l;
int r=ST->r;
if(x<=l&&y>=r)return ST->sum;
int mid=(l+r)>>1;
int ans=0;
if(x<=mid)ans+=query(ST->left,x,y);
if(y>mid)ans+=query(ST->right,x,y);
return ans;
}
更新线段树
void update(SegTree ST,int idx,int x){
if(ST==NULL)return;
int l=ST->l;
if(l==idx){
ST->sum=x;
return;
}
int r=ST->r;
int mid=(l+r)>>1;
if(idx<=mid){
update(ST->left,idx,x);
}else{
update(ST->right,idx,x);
}
ST->sum=ST->left->sum+ST->right->sum;
}
到目前为止这样就凑齐了线段树的所有代码,接下来测试一下
int main() {
int t[10000];
for(int i=0;i<9999;i++){
t[i]=i+1;
}
SegTree ST=buildSegTree(0,9999,t);
printf("Sum = %d",query(ST,0,9999));
return 0;
}
结果正确
如果修改1下标的值为3(原来是2)
int main() {
int t[10000];
for(int i=0;i<9999;i++){
t[i]=i+1;
}
SegTree ST=buildSegTree(0,9999,t);
update(ST,1,3); //修改1下标上的值为3
printf(“Sum = %d”,query(ST,0,9999));
return 0;
}
刚好比原来多1,可见代码没有问题.