zoukankan      html  css  js  c++  java
  • 线段树学习

    原文转自:http://blog.csdn.net/dgq8211/article/details/7407753

    先从书上把定义抄下来:

    一棵二叉树,记为 T (a,b),参数 a,b表示该节点表示区间[a,b)。区间的长度b-a 记为 L。

    递归定义 T[a,b]: 

    若 L>1 :[a, (a+b)/2]为 T 的左儿子,[(a+b) /2,b]为 T 的右儿子。 

    若 L=1 :T 为一个叶子节点。

    区间[1, 10]的线段树表示方法如下: 

    这里需要注意一点,图中一共有9个叶子节点,也就是说,这棵树只能代表9个点的数据,也就是[1,9]区间的数据。

    所以,我们在对待线段树区间的时候,可以理解为[a,b),即左闭右开。这样,它的叶子节点也就只代表一个点a。

    首先,线段树是一个完全二叉树。它有以下性质:

    具有n个结点的完全二叉树的深度为[log(2)n]+1([ ]表示取上整)

    根据线段树是完全二叉树的这一性质,我们可以用数组保存结点,当然,结点中可以根据需要加些不同的值用来保存不同的信息。

    1. const int Max=pow(2,ceil(log2(Max_N))+1)    //数组最大值计算方法  

    每个结点的左右孩子可以直接用数组下标去找,左孩子是2*x,右孩子是2*x+1,父亲是x/2。(按照满二叉树运算,虽然浪费一些空间,但可以提高效率)

    强大的位运算:

    1. #define L(x) (x<<1)  
    2. #define R(x) (x<<1|1)  
    3. #define MID(x,y) ((x+y)>>1)  

    线段树构造:

    1. struct Tnode  
    2. {  
    3.     int l,r;                    //l,r表示此结点所代表区间的左右端点  
    4.     /*?*/                      //结构体里面还可以加东西,这里没有加  
    5. }node[Max];  
    6. void Build(int t,int l,int r)   //t表示数组下标,l、r表示区间左右端点  
    7. {  
    8.     node[t].l = l , node[t].r = r;//记录此结点所代表区间的左右端点  
    9.     if(l == r-1)        //已到叶子结点,不再向下递归建树  
    10.     {  
    11.         return ;  
    12.     }  
    13.     int mid = MID(l,r); //将区间分成两半  
    14.     Build(L(t),l,mid);  //建立此结点的左孩子  
    15.     Build(R(t),mid,r);  //建立此结点的右孩子  
    16. }  

    线段树查询:

      1. void Query(int t,int l,int r)   //t表示数组下标,l、r表示待查询区间左右端点  
      2. {  
      3.     if( node[t].l == l && node[t].r == r )//已经找到区间  
      4.     {  
      5.         return ;  
      6.     }  
      7.     int mid = MID(node[t].l,node[t].r);  
      8.     if(l >= mid)                //如果左端点大于mid,待查询区间一定在右孩子中。  
      9.         Query(R(t),l,r);  
      10.     else  
      11.         if(r <= mid)            //如果右端点小于mid,待查询区间一定在左孩子中。  
      12.             Query(L(t),l,r);  
      13.         else                    //如果不满足上述情况,将待查询区间分割成[l,mid)和[mid,r)继续查找  
      14.         {  
      15.             Query(L(t),l,mid);  
      16.             Query(R(t),mid,r);  
      17.         }  
      18. }  
  • 相关阅读:
    ExtJS4学习笔记二--表单控件相关
    Js中replace()的用法
    浅析轮询(Polling)和推送(LongPolling)服务
    ExtJS4学习笔记五--面板使用
    ExtJS4学习笔记四--图片上传
    spring MVC
    ExtJS4学习笔记三--远程访问数据源示例
    Struts 2
    ExtJs4学习笔记一--基础知识
    URL编码规则
  • 原文地址:https://www.cnblogs.com/10jschen/p/2667417.html
Copyright © 2011-2022 走看看