0
点赞
收藏
分享

微信扫一扫

线段树学习笔记

DYBOY 2022-09-26 阅读 48

之前就已经学过了,放在了本地,现在搬到博客园来~

     关于线段树的视频学习,强烈推荐B站此大佬的讲解:​​https://www.bilibili.com/video/BV1cb411t7AM​​

     1.概念:线段树是一种二叉搜索树,与区间树相似。线段树是建立在线段或区间基础上的树,树的每个结点代表一条线段[L,R]。

    2:根据视频里的内容,我做出了这张图。arr[]数组,求它区间和,以及对它进行某些数的修改

线段树学习笔记_线段树

根据此,有build_tree:

void build_tree(int node,int start,int end)
{
if(start==end)
{
tree[node]=arr[start];
}
else
{
int mid=(start+end)/2;
int left_node=node*2+1;
int right_node=node*2+2;
build_tree(left_node,start,mid);
build_tree(right_node,mid+1,end);
tree[node]=tree[left_node]+tree[right_node];
}
}

对于update,需要修改arr[]的某个数,改变最下面的start==end的结点,那么上面跟它有关系的结点都要进行更新。start==end依然是作为递归的出口。看idx的位置,在左孩子里就更新左孩子,否则右孩子。

void update_tree(int node,int start,int end,int idx,int val)
{
if(start==end)
{
tree[node]=val;
arr[idx]=val;
}
else
{
int mid=(start+end)/2;
int left_node=node*2+1;
int right_node=node*2+2;
if(idx>=start&&idx<=mid)
update_tree(left_node,start,mid,idx,val);
else
update_tree(right_node,mid+1,end,idx,val);
tree[node]=tree[left_node]+tree[right_node];
}

}

然后是求区间和操作。基本一致。只是这里要注意一下递归结束条件的优化:

线段树学习笔记_#include_02

int query_tree(int arr[],int tree[],int node ,int start,int end,int l,int r)
{
if(r<start||l>end)
{
return 0;
}
else if(l<=start&&end<=r)  
{
return tree[node];
}
else if(start==end)
{
return tree[node];
}
else
{
int mid=(start+end)/2;
int left_node=node*2+1;
int right_node=node*2+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;
}

}

总的代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1000;
void build_tree(int arr[],int tree[],int node,int start,int end)
{
if(start==end){
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)
{
if(start==end)
{
arr[idx]=val;
tree[node]=val;
}
else
{
int mid=(start+end)/2;
int left_node=node*2+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)
{
if(r<start||l>end)
{
return 0;
}
else if(l<=start&&end<=r)
{
return tree[node];
}
else if(start==end)
{
return tree[node];
}
else
{
int mid=(start+end)/2;
int left_node=node*2+1;
int right_node=node*2+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[maxn]={0};
build_tree(arr,tree,0,0,size-1);
for(int i=0;i<15;i++)
cout<<tree[i]<<" ";
cout<<endl;
update_tree(arr,tree,0,0,size-1,4,6);
for(int i=0;i<15;i++)
cout<<tree[i]<<" ";
cout<<endl;
cout<<query_tree(arr,tree,0,0,size-1,2,4);
}

 



举报

相关推荐

0 条评论