线段树学习笔记

给你一囗甜甜゛ 提交于 2020-02-11 23:41:00

当要处理一个数组arr,求一定长度的和,并且对数组的单个值的大小进行修改。不进行特殊处理的话,不妨假设一定长度为n,那么求和的时间复杂度为O(n),修改为O(1)。

如果使用另外一个数组s,为arr的前缀和数组,那么求和的时间复杂度变为O(1),但是修改的时间复杂度变为O(n)。

这样的处理显然并不是很理想。

但使用线段树组进行处理的话,能让求和和修改的时间复杂度变为O(nlogn),从而达到减少时间复杂度的目的。

1.建立一个树状数组。

void build_tree(int arr[],int tree[],int node,int start,int endd)
{
    if(start==endd)
        tree[node]=arr[endd];//递归的出口
    else
    {
        int mid=(start+endd)/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,endd);
        tree[node]=tree[left_node]+tree[right_node];
    }
}

思路其实就是父亲等于左儿子+右儿子。

一直递归下去,直到出口。

2.对数组的区间值的询问

int query_tree(int arr[],int tree[],int node,int start,int endd,int L,int R)
{
    printf("start=%d\n",start);
    printf("endd=%d\n",endd);
    cout<<endl;
    if(start>R||endd<L)
    {
        return 0;
    }
    else if(L<=start&&endd<=R)
    {
        return tree[node];
    }//递归出口
    else if(start==endd)
    {
        return tree[node];
    }
    {
        int mid=(start+endd)/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,endd,L,R);
        return sum_left+sum_right;
    }
}

计算【L,R】区间上的值。

从根节点开始查询,走左枝还是右枝,对于不在范围内的返回0。

3.对特定值的修改

void update_tree(int arr[],int tree[],int node,int start,int endd,int idx,int val)
{
    if(start==endd)
    {
        arr[idx]=val;
        tree[node]=val;
    }
    else
    {
        int mid=(start+endd)/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,endd,idx,val);
        }
        tree[node]=tree[left_node]+tree[right_node];
    }
}

将arr[idx]=val。先找到包含idx的那条枝,然后将其进行修改。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!