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

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

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

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

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

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

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

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

()将查询数据Q从根节点开始,按照Q与各个节点的比较结果向下遍历,直到到达叶子节点为止。

到达叶子节点时,计算Q与叶子节点上保存的所有数据之间的距离,记录最小距离对应的数据点,

假设当前最邻近点为p_cur,最小距离记为d_cur

()进行回溯操作,该操作的目的是找离Q更近的数据点,即在未访问过的分支里,是否还有离Q更近的点

它们的距离小于d_cur

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

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

敲的好累啊!!

 #include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF=;
const int mod=;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,F,rt,ans=INF;
int x[],y[];
struct P
{
int d[],mn[],mx[],l,r;
int& operator[](int x)
{
return d[x];
}
friend bool operator<(P a,P b)
{
return a[F]<b[F];
}
friend int dis(P a,P b)
{
return abs(a[]-b[])+abs(a[]-b[]);
}
}p[];
struct kdtree
{
P t[],T;
int ans;
void update(int k)
{
int l=t[k].l,r=t[k].r;
for(int i=;i<;i++)
{
t[k].mn[i]=t[k].mx[i]=t[k][i];
if(l) t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);
if(r) t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);
if(l) t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);
if(r) t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);
}
}
int build(int l,int r,int now)
{
F=now;
int mid=(l+r)>>;
nth_element(p+l,p+mid,p+r+);
t[mid]=p[mid];
for(int i=;i<;i++)
t[mid].mn[i]=t[mid].mx[i]=t[mid][i];
if(l<mid) t[mid].l=build(l,mid-,now^);
if(r>mid) t[mid].r=build(mid+,r,now^);
update(mid);
return mid;
}
int getmn(P a)
{
int ans=;
for(int i=;i<;i++)
{
ans+=max(T[i]-a.mx[i],);
ans+=max(a.mn[i]-T[i],);
}
return ans;
}
int getmx(P a)
{
int ans=;
for(int i=;i<;i++)
ans+=max(abs(T[i]-a.mx[i]),abs(T[i]-a.mn[i]));
return ans;
}
void querymx(int k)
{
ans=max(ans,dis(t[k],T));
int l=t[k].l,r=t[k].r,dl=-INF,dr=-INF;
if(l) dl=getmx(t[l]);if(r) dr=getmx(t[r]);
if(dl>dr)
{
if(dl>ans)querymx(l);
if(dr>ans)querymx(r);
}
else
{
if(dr>ans)querymx(r);
if(dl>ans)querymx(l);
}
}
void querymn(int k)
{
int tmp=dis(t[k],T);
if(tmp)ans=min(ans,tmp);
int l=t[k].l,r=t[k].r,dl=INF,dr=INF;
if(l)dl=getmn(t[l]);if(r)dr=getmn(t[r]);
if(dl<dr)
{
if(dl<ans)querymn(l);
if(dr<ans)querymn(r);
}
else
{
if(dr<ans)querymn(r);
if(dl<ans)querymn(l);
}
}
int query(int f,int x,int y)
{
T[]=x;T[]=y;
if(f==)ans=INF,querymn(rt);
else ans=-INF,querymx(rt);
return ans;
}
}kdtree;
int main()
{
n=read();
for(int i=;i<=n;i++)
{
x[i]=read(),y[i]=read();
p[i][]=x[i];p[i][]=y[i];
}
rt=kdtree.build(,n,);
for(int i=;i<=n;i++)
{
int mn=kdtree.query(,x[i],y[i]),mx=kdtree.query(,x[i],y[i]);
ans=min(ans,mx-mn);
}
printf("%d\n",ans);
return ;
}

数据结构:K-D树的更多相关文章

  1. 【经典数据结构】B树与B+树

    本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 维基百科对B树的定义为“在计算机科学中,B树 ...

  2. 数据结构---平衡查找树之B树和B+树(转)

    本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 前面讲解了平衡查找树中的2-3树以及其实现红 ...

  3. 【经典数据结构】B树与B+树(转)

    本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 维基百科对B树的定义为“在计算机科学中,B树 ...

  4. 【经典数据结构】B树与B+树的解释

    本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 前面讲解了平衡查找树中的2-3树以及其实现红 ...

  5. 数据结构-PHP 线段树的实现

    转: 数据结构-PHP 线段树的实现 1.线段树介绍 线段树是基于区间的统计查询,线段树是一种 二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.使用线段树可以快速的查 ...

  6. D&F学数据结构系列——B树(B-树和B+树)介绍

    B树 定义:一棵B树T是具有如下性质的有根树: 1)每个节点X有以下域: a)n[x],当前存储在X节点中的关键字数, b)n[x]个关键字本身,以非降序存放,因此key1[x]<=key2[x ...

  7. Go 数据结构--二分查找树

    Go 数据结构--二分查找树 今天开始一个Go实现常见数据结构的系列吧.有时间会更新其他数据结构. 一些概念 二叉树:二叉树是每个节点最多有两个子树的树结构. 完全二叉树:若设二叉树的高度为h,除第 ...

  8. Linux 内核中的数据结构:基数树(radix tree)

    转自:https://www.cnblogs.com/wuchanming/p/3824990.html   基数(radix)树 Linux基数树(radix tree)是将指针与long整数键值相 ...

  9. 【BZOJ】3196: Tyvj 1730 二逼平衡树(区间第k小+树套树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3196 Treap+树状数组 1WA1A,好伤心,本来是可以直接1A的,这次开始我并没有看题解,就写出 ...

  10. Python数据结构应用6——树

    数据结构中的树的结点和机器学习中决策树的结点有一个很大的不同就是,数据结构中的树的每个叶结点都是独立的. 树的高度(Height)指叶结点的最大层树(不包含根结点) 一.树的建立 树可以这样定义:一棵 ...

随机推荐

  1. Zen Coding && Emmet-Sublime 安装

    Sublime Text 插件之:Emmet,旧版称:ex-Zen Coding 更名之后增加了CSS3和HTML5许多新特性.项目地址也从 code.google 移 github. 安装: Pac ...

  2. JS中通过数组的方式操作字符串 数组是个好东西 ....

    题目:使用JS将 var str="what are you nong sha lei",通过您的方法转换为"What Are You Nong Sha Lei" ...

  3. Python中的namespace package

    在Python 3.3之前,一个目录想被当成package被导入,必须包含__init__.py文件:而在Python 3.3及以后的版本中,__init__.py文件可以不需要,直接使用import ...

  4. Thinkphp5获取数据库数据到视图

    这是学习thinkhp5的基础篇笔记. 本文主要讲怎么配置数据库链接,以及查询数据库数据,并且最后将数据赋给视图. 数据库配置: thinkphp5的数据库配置默认在conf下的database.ph ...

  5. Maven 3-Maven依赖版本冲突的分析及解决小结 (阿里,美团,京东面试)

    举例A依赖于B及C,而B又依赖于X.Y,而C依赖于X.M,则A除引B及C的依赖包下,还会引入X,Y,M的依赖包(一般情况下了,Maven可通过<scope>等若干种方式控制传递依赖).这里 ...

  6. Java内存分配及垃圾回收机制

    Java内存区域 1.内存区域 jvm运行时数据区域 程序计数器 Java虚拟机栈 本地方法栈 方法区 Java堆 大图 2.概念解释 程序计数器   线程私有的一块很小的内存空间,它是当前线程所执行 ...

  7. JDK各个版本比较 JDK5~JDK9

    JDK5 自动装箱与拆箱: 枚举 静态导入,如:import staticjava.lang.System.out 可变参数(Varargs) 内省(Introspector),主要用于操作JavaB ...

  8. SQL局部变量

    声明局部变量 局部变量的声明需要使用declare 语句.并且必须以@开头 declare { @varaible_name datatype[,...n] } varaible_name :局部变量 ...

  9. 【Asp.Net Core】ASP.NET Core 2.0 + EF6 + Linux +MySql混搭

    好消息!特好消息!同时使用ASP.NET Core 2.0和.NET Framework类库还能运行在linux上的方法来啦! 是的,你没有看错!ASP.NET Core 2.0,.NET Frame ...

  10. BZOJ 1797 最小割(最小割割边唯一性判定)

    问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断? 现在请你回答这两个问题. 最小割唯一性判定 jcvb: 在残余网络上跑ta ...