线段树定义:
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
[1]
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
主要遇到的问题:
要解决计算某一数组任意区间长度,并且在随机改变一个值后,在计算这个区间和
运用线段树可以降低时间复杂度。
主要涉及三个函数
1.根据所给数组,创建一个线段树(满二叉树,不够补0)
2.改变一个值,更新线段树
3.计算L-R的区间和
下面为程序代码:
//线段树
//主要解决问题,在一串数组中计算随机长度的的和,并随机改变任意的值,再算其长度
#include<stdio.h>
#define MAX_LEN 1000
void build_tree(int arr[],int tree[],int node,int start,int end)
{
if(start==end) //node是把树展开,对应的下标的值
{
tree[node]=arr[start];
}
else
{
int mid=(start+end)/2;
int left_node=2*node+1; //左子树
int right_node=2*node+2; //右子树
build_tree(arr,tree,left_node,start,mid);
build_tree(arr,tree,right_node,mid+1,end);
tree[node]=tree[left_node]+tree[right_node];
}
}
void update_tree(int arr[],int tree[],int node,int start,int end,int idx,int val)//idx:待改变的数组下标,val:改成的值
//这条路上的根节点都需要更新
{
if(start==end)
{
arr[idx]=val;
tree[node]=val;
}
else
{
int mid=(start+end)/2;
int left_node=2*node+1; //左子树
int right_node=2*node+2; //右子树
if(idx>=start&&idx<=mid) //在左子树
{
update_tree(arr,tree,left_node,start,mid,idx,val);
}
else
{
update_tree(arr,tree,right_node,mid+1,end,idx,val);
}
tree[node]=tree[left_node]+tree[right_node];
}
}
int query_tree(int arr[],int tree[],int node,int start,int end,int L,int R) //求arr[]L到R的和
{
printf(" start = %d\n",start);
printf(" end = %d\n",end);
printf("\n");
if(R<start||L>end) //不在范围内
{
return 0;
}
else if(start>=L&&end<=R) //start end 完全在L R范围内,不需要向下递归
{
return tree[node];
}
else if(start==end)
{
return tree[node];
}
else
{
int mid=(start+end)/2;
int left_node=2*node+1; //左子树
int right_node=2*node+2; //右子树
int sum_left=query_tree(arr,tree,left_node,start,mid,L,R);
int sum_right=query_tree(arr,tree,right_node,mid+1,end,L,R);
return sum_left+sum_right;
}
}
int main()
{
int arr[]={1,3,5,7,9,11};
int size=6;
int tree[MAX_LEN]={0};
build_tree(arr,tree,0,0,size-1);
for(int i=0;i<15;i++) //15是根据二叉树算出来的
{
printf("%d ",tree[i]);
}
printf("\n");
update_tree(arr,tree,0,0,size-1,1,4); //将3换成4
for(int i=0;i<15;i++) //15是根据二叉树算出来的
{
printf("%d ", tree[i]);
}
printf("\n");
int sum=query_tree(arr,tree,0,0,size-1,0,4);
printf("%d",sum);
return 0;
}