线段树学习笔记

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

     关于线段树的视频学习,强烈推荐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];        
    }

}

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

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);
}

 

posted @ 2020-04-11 23:17  liyexin  阅读(135)  评论(0编辑  收藏  举报