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. 【转】C++后台开发之我见

    工作也快两年了,偶然看到自己以前写过的一些技术博客,发现自己自毕业后一直没有更新过自己的技术博客,趁现在是刚过完春节快要回公司工作之际,谈谈我个人对后台开发的一些个人见解,希望能够对在校的学生或者刚刚 ...

  2. 动态内存&对象

    一.对象的生存期 对于 static 对象和自动对象,它们都有着严格定义的生存期. 全局对象:在程序启动时分配,在程序结束时销毁. 局部自动对象:在对象定义语句时分配,在离开块时销毁 局部 stati ...

  3. oracle数据库之PL/SQL 块结构和组成元素

    一.PL/SQL 块 (一)PL/SQL 程序由三个块组成,即声明部分.执行部分.异常处理部分 PL/SQL 块的结构如下: 1.DECLARE /* 声明部分: 在此声明 PL/SQL 用到的变量, ...

  4. angular4中使用jquer插件

    有以下办法 1 在html文档头部引入jquery插件依赖,但是文档一旦变动就麻烦了 2 使用指令:http://www.cnblogs.com/liuyt/p/5810100.html 指令是把利器 ...

  5. 百度安卓sdk开发

    一 key问题 1 在百度地图api控制台申请key的流程主要用到了app包,开发工具的开发sha1和发布sha1值,这2个值的获取就非常关键了. 一般来说我们都是在windows上开发安卓,使用an ...

  6. 3dContactPointAnnotationTool开发日志(十四)

      貌似每次让用户手动输入文件路径太不人道了,于是参考Unity 实用教程 之 调用系统窗口选择文件或路径增加了让用户浏览文件的功能,点击输入框旁边的+就可以找到文件并加载进来:   貌似调整位置再计 ...

  7. 【Linux】- ps -ef |grep 命令

    ps:将某个进程显示出来 grep:查找 |:管道命令 表示ps命令与grep同时执行 PS是LINUX下最常用的也是非常强大的进程查看命令 grep命令是查找,是一种强大的文本搜索工具,它能使用正则 ...

  8. django 安装/部署过程

    一.软件安装 1.升级linux中的python   参考“centos升级python” 2.安装apache(httpd) 3.安装django,先要安装setuptools    参考“安装dj ...

  9. QT分析之消息事件机制

    原文地址:http://blog.163.com/net_worm/blog/static/127702419201001432028526/ 上回我们分析到QPushButton的初始化,知道了Wi ...

  10. linux路由表的配置

    linux路由表的配置 一.原理说明 1.路由表(table)从0到255进行编号,每个编号可以对应一个别名,编号和别名的对应关系在linux下放在/etc/iproute2/rt_tables这个文 ...