线段树 (真正的二叉树版 擅长二叉树与指针的人可以看我修改的版本,是在网上的数组版本上修改的)

线段树 (真正的二叉树版 擅长二叉树与指针的人可以看我修改的版本,是在网上的数组版本上修改的)采用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,可见代码没有问题.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值