zoukankan      html  css  js  c++  java
  • 线段树(数组实现)

    最近看了很多学长发的资料,吸取了别人的优点,把query函数更改的更加合理了。

    —————————————————————我是分割线———————————————————————————————————————————— 

     线段树是一棵完美二叉树,树上的每个节点都维护一个区间。根维护的是整个区间,每个节点维护的是父亲的区间二等分后的其中一个子区间。当有n个元素时,对区间的操作可以在O(logn)的时间内完成。

      所以,线段树是擅长处理区间的!

      从网上找了一个图:

      线段树

    RMQ(range minimum query)问题:

      在给定数列a0,a1...an,给定s和t,线段树可以求as...at的最值,以求最小值为例,如下图:

      

      每个节点维护对应区间的最小值,例如根节点维护的是下标1到8的最小值,左子树维护的是1到4,右子书维护的是5到6,以此类推。

      建树时,父节点取左右子节点的较小者。我比较喜欢用数组建树,因为非常简单清晰,下面是初始化线段树的代码:

      

    1 #define max 999999999
    2 int k,n,tree[10005];//n这里是数列里数字的个数
    3 void init(){
    4     k=1;//k这里是树最后一层的叶子个数
    5     while(k<n)//除第一层外,树的每一层都有2的n次方个节点,所以这里求的是k大于n的最小节点数
    6         k<<=1;//输入的数字个数n可能小于最下面一层的叶子数
    7     for(int i=1;i<=2*k-1;i++)//2*k-1是整个树节点的个数,全部设置为max,反正父节点取的是较小者
    8         tree[i]=max;
    9 }

      n小于k时,树最后一层的其他值已经是max,所以不影响父节点,下面是线段树每插入一个值的更新:

    1 void update(int pos,int val){//pos是树的下标,val是数的值
    2     pos+=k-1;//这里数组下标是从1到n,树的下标也是从1到n,这就是叶子节点与数组下标的对应关系,大家可以画一画
    3     tree[pos]=val;
    4     while(k>1){
    5         pos/=2;//父节点
    6         tree[pos]=tree[pos*2]<tree[pos*2+1]?tree[pos*2]:tree[pos*2+1];
    7     }
    8 }

      下面比较关键的是给定下标区间查找,我会在注释里说明:

     1 //调用时query(输入a,输入b,1,1,k)
     2 int query(int a,int b,int pos,int l,int r){//a和b是想要查找的下标区间,l和r是当前节点维护的下标区间,pos是当前节点下标
     3     if(a<=l&&b>=r)//查找终结的条件就是想查找的区间大于节点维护的区间
     4         return tree[pos];
     5     int mid = (l+r)/2;
     6     if(a<=m)
     7         int a = query(a,b,pos*2,l,m);
     8     if(b>m)
     9         int b = query(a,b,pos*2+1,m+1,r);
    10     return a<b?a:b;
    11 }

      OK,到这里,基本的算法就实现了,注意一下树的大小一定要合适。第一篇博客,有些地方想讲清楚可能讲的还不透彻,等我的理解更加深入之后,会继续修改的,如果有错误,希望大家指正,我会虚心接受的~

      

  • 相关阅读:
    MM1排队系统
    java基本概念
    将博客搬至CSDN
    数据库知识点1
    离散分布
    概率论1--基本概念
    一道经典JS题(关于this)
    ajax请求过程中下载文件在火狐下的兼容问题
    熟悉css/css3颜色属性
    打字机游戏Ⅱ之手速pk
  • 原文地址:https://www.cnblogs.com/zqy123/p/4899197.html
Copyright © 2011-2022 走看看