zoukankan      html  css  js  c++  java
  • 线段树的两种建树模型

    线段树的两种建树模式:

    第一种:端点形式

    比如对区间[0,8]可以建立如下的线段树:

    [0,8]

    [0,4][4,8]

    [0,2][2,4][4,6][6,8]

    [0,1][1,2][2,3][3,4][4,5][5,6][6,7][7,8]

    第二种:区间格形式

    比如对区间[0,8]可以建立如下的线段树:

    [1,8]

    [1,4][5,8]

    [1,2][3,4][5,6][7,8]

    [1,1][2,2][3,3][4,4][5,5][6,6][7,7][8,8]

    在这种模型下,[1,1],[2,2]...代表的不是一个点,而是一个区间格.

    上面和下面的两棵线段树图上的每一个节点都是一一对应的.

    [0,8]->[1,8]

    [0,4]->[1,4]

    [4,8]->[5,8]

    ...

    第一种线段树模型对应的区间模型:

     |___|___|___|___|___|___|___|___|

       1           6     8

    第二种线段树模型对应的区间模型:

    |_1_|_2_|_3_|_4_|_5_|_6_|_7_|_8_|

    在第一种模型中,一个数字代表一个端点;

    在第二种模型中,一个数字代表一个区间格.

    模型上的差异,造成了建树过程的不同:

    //--------------------------------------------------------

    第一种模型的建树代码:

    struct line
    {
    int left,right;//左端点、右端点
    ......//其他扩展的属性
    };
    struct line a[100];
    //建立
    void build(int s,int t,int n)
    {int mid=(s+t)/2;
    a[n].left=s;
    a[n].right=t;
    if (s==t) return;
    build(s,mid,2*n);
    build(mid+1,t,2*n+1);
    }
    //插入
    void insert(int s,int t,int step)//要插入的线段的左端点和右端点、以及当前线段树中的某条线段
    {     if (s==a[step].left && t==a[step].right)
          {
                ......(具体的操作)
                return;//插入结束返回
          }
          if (a[step].left==a[step].right)   return;//当前线段树的线段没有儿子,插入结束返回
          int mid=(a[step].left+a[step].right)/2;
          if (mid>=t)    insert(s,t,step*2);//如果中点在t的右边,则应该插入到左儿子
          else if (mid<s)    insert(s,t,step*2+1);//如果中点在s的左边,则应该插入到右儿子
          else//否则,中点一定在s和t之间,把待插线段分成两半分别插到左右儿子里面
          {
                insert(s,mid,step*2);
                insert(mid+1,t,step*2+1);
          }
    }
    //----------------------------------------------------------


    第二种线段树的建树代码:

    struct line
    {
    int left,right;
    ......//其他扩展的属性
    };
    struct line a[100];
    //建立
    void build(int s,int t,int n)
    {int mid=(s+t)/2;
    a[n].left=s;
    a[n].right=t;
    if (s==t-1) return;//这里的终止条件改为s == t-1
    build(s,mid,2*n);
    build(mid,t,2*n+1);//这里改mid+1为mid
    }
    int main()
    {
    ...
    build(1,n,1);
    } 
    //插入
    void insert(int s,int t,int step)
    {     if (s==a[step].left && t==a[step].right)
          {
                ......(具体的操作)
                return;
          }
         //下面的终止条件改了
          if (a[step].left==a[step].right-1)   return;
          int mid=(a[step].left+a[step].right)/2;
          if (mid>=t)    insert(s,t,step*2);
          else if (mid<s)    insert(s,t,step*2+1);
          else
          {
                insert(s,mid,step*2);
                insert(mid,t,step*2+1);这里改mid+1为mid
          }
    }
    int main()
    {
    ......
    build(0,n,1);
    }


  • 相关阅读:
    加签验签
    .net core三个生命周期
    List,IList,IEnumerable的区别
    IHttpClientFactory 模拟http请求
    TDengine在Linux下的安装
    Linux环境下安装jdk
    在 React 中使用 JSX 的好处
    React介绍(讲人话)
    React是什么,为什么要使用它?
    mac系统下给文件夹加密方法
  • 原文地址:https://www.cnblogs.com/java20130726/p/3218226.html
Copyright © 2011-2022 走看看