zoukankan      html  css  js  c++  java
  • 数据结构:K-D树

     K-D树实际上是一棵高维二叉搜索树,与普通二叉搜索树不同的是,树中存储的是一些K维数据

    普通的二叉搜索树是一维的,当推广到K维后,就是我们的K-D树了

    在K-D树中跟二叉搜索树差不多,也是将一个K维的数据与根节点进行比较,然后划分的

    这里的比较不是整体的比较,而是选择其中一个维度来进行比较

    在K-D树进行划分时,可以每次选择方差最大的属性来划分数据到左右子树

    在K-D树的划分中,这个轴的选取很关键,要保证划分后的左右子树尽量平衡

    那么很显然选取这个属性的值对应数组的中位数作为pivot

    然后是查找了,最邻近查找的算法描述如下

    1)将查询数据Q从根节点开始,按照Q与各个节点的比较结果向下遍历,直到到达叶子节点为止。
    
    到达叶子节点时,计算Q与叶子节点上保存的所有数据之间的距离,记录最小距离对应的数据点,
    
    假设当前最邻近点为p_cur,最小距离记为d_cur
    
    (2)进行回溯操作,该操作的目的是找离Q更近的数据点,即在未访问过的分支里,是否还有离Q更近的点
    
    它们的距离小于d_cur

    然后一道模板题,BZOJ1941,给出平面上n个点,求距离每个点最大距离减最小距离(不算自己)的最小值

    枚举每个点找最近点,最远点更新答案

    敲的好累啊!!

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<algorithm>
      4 using namespace std;
      5 const int INF=1000000000;
      6 const int mod=1000000007;
      7 int read()
      8 {
      9     int x=0,f=1;char ch=getchar();
     10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     12     return x*f;
     13 }
     14 int n,F,rt,ans=INF;
     15 int x[500005],y[500005];
     16 struct P
     17 {
     18     int d[2],mn[2],mx[2],l,r;
     19     int& operator[](int x)
     20     {
     21         return d[x];
     22     }
     23     friend bool operator<(P a,P b)
     24     {
     25         return a[F]<b[F];
     26     }
     27     friend int dis(P a,P b)
     28     {
     29         return abs(a[1]-b[1])+abs(a[0]-b[0]);
     30     }
     31 }p[500005];
     32 struct kdtree
     33 {
     34     P t[500005],T;
     35     int ans;
     36     void update(int k)
     37     {
     38         int l=t[k].l,r=t[k].r;
     39         for(int i=0;i<2;i++)
     40         {
     41             t[k].mn[i]=t[k].mx[i]=t[k][i];
     42             if(l) t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);
     43             if(r) t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);
     44             if(l) t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);
     45             if(r) t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);
     46         }
     47     }
     48     int build(int l,int r,int now)
     49     {
     50         F=now;
     51         int mid=(l+r)>>1;
     52         nth_element(p+l,p+mid,p+r+1);
     53         t[mid]=p[mid];
     54         for(int i=0;i<2;i++)
     55             t[mid].mn[i]=t[mid].mx[i]=t[mid][i];
     56             if(l<mid) t[mid].l=build(l,mid-1,now^1);
     57             if(r>mid) t[mid].r=build(mid+1,r,now^1);
     58             update(mid);
     59             return mid;
     60     }
     61     int getmn(P a)
     62     {
     63         int ans=0;
     64         for(int i=0;i<2;i++)
     65         {
     66             ans+=max(T[i]-a.mx[i],0);
     67             ans+=max(a.mn[i]-T[i],0);
     68         }
     69         return ans;
     70     }
     71     int getmx(P a)
     72     {
     73         int ans=0;
     74         for(int i=0;i<2;i++)
     75             ans+=max(abs(T[i]-a.mx[i]),abs(T[i]-a.mn[i]));
     76         return ans;
     77     }
     78     void querymx(int k)
     79     {
     80         ans=max(ans,dis(t[k],T));
     81         int l=t[k].l,r=t[k].r,dl=-INF,dr=-INF;
     82         if(l) dl=getmx(t[l]);if(r) dr=getmx(t[r]);
     83         if(dl>dr)
     84         {
     85             if(dl>ans)querymx(l);
     86             if(dr>ans)querymx(r);
     87         }
     88         else 
     89         {
     90             if(dr>ans)querymx(r);
     91             if(dl>ans)querymx(l);
     92         }
     93     }
     94     void querymn(int k)
     95     {
     96         int tmp=dis(t[k],T);
     97         if(tmp)ans=min(ans,tmp);
     98         int l=t[k].l,r=t[k].r,dl=INF,dr=INF;
     99         if(l)dl=getmn(t[l]);if(r)dr=getmn(t[r]);
    100         if(dl<dr)
    101         {
    102             if(dl<ans)querymn(l);
    103             if(dr<ans)querymn(r);
    104         }
    105         else 
    106         {
    107             if(dr<ans)querymn(r);
    108             if(dl<ans)querymn(l);
    109         }
    110     }
    111     int query(int f,int x,int y)
    112     {
    113         T[0]=x;T[1]=y;
    114         if(f==0)ans=INF,querymn(rt);
    115         else ans=-INF,querymx(rt);
    116         return ans;
    117     }
    118 }kdtree;
    119 int main()
    120 {
    121     n=read();
    122     for(int i=1;i<=n;i++)
    123     {
    124         x[i]=read(),y[i]=read();
    125         p[i][0]=x[i];p[i][1]=y[i];
    126     }
    127     rt=kdtree.build(1,n,0);
    128     for(int i=1;i<=n;i++)
    129     {
    130         int mn=kdtree.query(0,x[i],y[i]),mx=kdtree.query(1,x[i],y[i]);
    131         ans=min(ans,mx-mn);
    132     }
    133     printf("%d
    ",ans);
    134     return 0;
    135 }
  • 相关阅读:
    用java实现的微信公众号爬虫
    装饰模式
    输入一个数,查询该数是否为素数
    Machine-learning-DecisionTree
    Circles of Waiting
    GRE阅读
    云数据库POLARDB产品解读之二:如何做到高性价比
    奉上一份云上数据安全保护指南
    从双十一看阿里云安全的“创世纪”——采访阿里云安全掌门人肖力有感
    阿里云移动研发平台EMAS,是如何连续5年安全护航双11的?
  • 原文地址:https://www.cnblogs.com/aininot260/p/9531863.html
Copyright © 2011-2022 走看看