KD树,你看着他好几个维度不明白,但实际上非常简单

\(K\)指维度 因此他可以在二维(多维)平面内进行搜索!!!

1.二维

1.1 建树

对于每一层,我们使用轮转法进行建树 什么意思呢?比如二维,如果\(x\)层为一维(横坐标),则\((x+1)\)层为二维(纵坐标)

确定好维数,接下来就是构建了。

此处用一张平面直角坐标系图来进行举例说明

已知二维平面点集\({(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)}\)

首先进行排序,排完后如下:

\({(2,3),(4,7),(5,4),(7,2),(8,1),(9,6)}\)

将其作图,得:



第一轮在\(x\)轴上进行划分(竖着切),找中点,得\((7,2)\)

则有图:



然后就有问题了

没法确定左右子树的根节点啊

于是递归

因为是第二轮,所以横着在\(y\)轴上划分

首先划分相对的左子树,找中点,得图:



因此完整构建左子树

然后构建右子树(\(y\)轴)

两个点,我习惯性将在上的设为中点,则得图:



因此构建出树:



可以看到,每一次划分都用一条水平线或垂直线将平面分成相等的两部分(二分思想),得到的两个子空间单座左右节点,即二分过程

1.2 计算中位数

nth_element(ps+l,ps+mid,ps+r)解决的问题不必多讲 但是不会排序数组!!!

1.3 代码

struct kdTree {
point p; // 直接存储对象
kdTree ls, rs; // 对象实例
}; /kdtree-build
void build(int l, int r, int rt = 1, int dep = 0)
{
if (l > r)
return;
son[rt] = r - l; // 当前节点子树元素数量
son[rt * 2] = son[rt * 2 + 1] = -1; // 初始化子节点为无效值
idx = dep % k; // 根据深度决定当前分割维度
int mid = (l + r) / 2; // 计算当前区间中点 // 快速选择算法,将中位数元素放到mid位置
nth_element(po + l, po + mid, po + r + 1);
pt[rt] = po[mid]; // 当前节点存储中位数点 // 递归构建左右子树
build(l, mid - 1, rt * 2, dep + 1); // 左子树区间[l,mid-1]
build(mid + 1, r, rt * 2 + 1, dep + 1); // 右子树区间[mid+1,r]
}

2.插入

2.1 思路

与二叉查找树类似,假设现在要将新增点插入到节点\(x\)的子树中,那么通过比较新增点的大小,来确定是左/右子树

(小左大右)

2.2 代码

void insert(kdTree* &o,const point &p)
{
if(o==nullptr) // 当前节点为空时创建新节点
{
o=new kdTree(p); // 初始化新节点存储目标点
return;
}
int d=cmp(p,o->p)^1; // 比较当前维度坐标(异或1实现维度交替)
dimension ^=1; // 切换分割维度
insert(o->ch[d],p); // 递归插入对应子树
o->maintain(); // 更新节点统计信息(如子树大小等)
}

3.查询

3.1 思路

对于每个节点,判断其对应的k维超矩形是否与查询超矩形有交集。

1.如果当前超矩形与查询超矩形不相交,则跳过该节点。

2.如果当前超矩形完全包含在查询超矩形内,则将该节点及其子树中的所有点添加到结果集。

3.如果当前超矩形与查询超矩形部分相交,则递归查询左右子树。



ps.超矩形你可以理解为一大块空间,放到二维上比

3.2 代码

可惜啦 这里没有代码

这就是\(manacher\)的思路,回去好好想想,看看自己是否学会!

4.查找最近/远点

4.1 思路

这里以查找远点为例,就是由远及近的一个思想,看着代码理解

4.2代码

void query(kdTree* o,const point &p)
{
if(o==nullptr) return;
ans=min(ans,dis(o.p,p)); // 更新最近距离
int d=o.ls.dis(p)>o.rs.dis(p); // 比较左右子树到目标点的距离,选择更远的分支
query(o.ch[d],p); // 优先搜索更远的分支(剪枝优化)
if(o.ch[d^1].dis(p)<ans) // 检查另一分支是否可能有更近点
query(o.ch[d^1],p); // 递归搜索另一分支
}

5.例题

1.摆棋子

2.查找k远点

都是模板题,只不过一个是远,一个是近,这里就不解析了(反正也是模板题

完结撒花!!!

[算法]KD树的更多相关文章

  1. KNN算法与Kd树

    最近邻法和k-近邻法 下面图片中只有三种豆,有三个豆是未知的种类,如何判定他们的种类? 提供一种思路,即:未知的豆离哪种豆最近就认为未知豆和该豆是同一种类.由此,我们引出最近邻算法的定义:为了判定未知 ...

  2. kd树的构建以及搜索

    构建算法 k-d树是一个二叉树,每个节点表示一个空间范围.表1给出的是k-d树每个节点中主要包含的数据结构. 表1 k-d树中每个节点的数据类型 域名 数据类型 描述 Node-data 数据矢量 数 ...

  3. 从K近邻算法谈到KD树、SIFT+BBF算法

    转自 http://blog.csdn.net/v_july_v/article/details/8203674 ,感谢july的辛勤劳动 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章 ...

  4. <转>从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    转自 http://blog.csdn.net/likika2012/article/details/39619687 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章待写:1.KD树:2.神经 ...

  5. 算法5-6:Kd树

    问题 给定一系列的点.和一个矩形.求矩形中包括的点的数量. 解答 这个问题能够通过建立矩阵来进行求解.首先将一个空间切割成矩阵,将点放置在相应的格子中.再计算矩形覆盖的格子.再推断格子中的点是否包括在 ...

  6. 从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    转载自:http://blog.csdn.net/v_july_v/article/details/8203674/ 从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 前言 前两日,在微博上说: ...

  7. 【特征匹配】SIFT原理之KD树+BBF算法解析

    转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/47606159 继上一篇中已经介绍了SIFT原理与C源代码剖析,最后得到了一系列 ...

  8. 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!

    1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...

  9. 【分类算法】K近邻(KNN) ——kd树(转载)

    K近邻(KNN)的核心算法是kd树,转载如下几个链接: [量化课堂]一只兔子帮你理解 kNN [量化课堂]kd 树算法之思路篇 [量化课堂]kd 树算法之详细篇

  10. kd树和knn算法的c语言实现

    基于kd树的knn的实现原理可以参考文末的链接,都是一些好文章. 这里参考了别人的代码.用c语言写的包括kd树的构建与查找k近邻的程序. code: #include<stdio.h> # ...

随机推荐

  1. to查完成绩的夏夏

    虽然不知道你现在看到的成绩是310还是340,抑或预估值域外的其他成绩,此刻我都想对你说你真的很棒! 还记得吗,一个人拖着个行李箱,来到陌生的城市二战,只有要去更大的世界的决心和傻气.有的时候会怀疑自 ...

  2. POWERBI_创建工作区应用_协同办公能力 up up up

    在powerbi中,我们往往会创建很多不同模型的报表,他们分别独立,但是在业务决策过程中,我们需要跨报表查看数据,反复切换报表,低效且忙乱 这个时候,合并展示报表是至关重要的 今天就一起学习一下,如何 ...

  3. 虚拟机搭建CDH6详细过程_三节点为例

    准备工作 一.安装虚拟机.centos 1.安装VMwareWorkstation虚拟化软件 首先我们使用VMwareWorkstation来快速的进行虚拟机的新建. 本文使用的版本为VMwareWo ...

  4. odoo14、15里tree上加button【系统原生功能】

    odoo14.15里面tree视图已经添加了跟form一样的header标签,后面列表写button可以由此处扩展 系统案例:注意:按钮要选择数据后才出现 代码如下: <tree string= ...

  5. netty发送socket短连接请求,自定义报文头

    package com.chinaums.japi.util; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; ...

  6. 前端WebSocket的方法封装

    一.封装方法 在项目根目录src下的utils中新增webSocketManager.js封装文件,代码内容如下: // webSocketManager.js /** WebSocketMessen ...

  7. 《Android开发——Android Studio的下载、安装与配置》

    Android开发--Android Studio的下载.安装与配置 一.下载: Android Studio最新的版本有一些BUG,不稳定,推荐安装老版本. 在正式安装Android Studio之 ...

  8. 故障诊断:ASM莫名出现GC等待事件、ADG的MRP进程HANG住

    我们的文章会在微信公众号Oracle恢复实录和博客网站同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳. ASM环境中有G ...

  9. 慢查询导致任务执行hang住

    上线上了大半天,原因:因为慢查询了导致跑不出来,后来同事帮忙看了下发现慢查询了,程序hang住了 select * from table where cdate = '2023-02-01' and ...

  10. 阿里微服务解决方案-Alibaba Cloud之父工程搭建(一)

    一.创建父工程 1.1 选择 File -> Project 1.2 选择创建 Maven 项目 1.3 输入父工程名称和选择项目路径 如图所示,父工程就搭建好了 1.4 在父工程pom.xml ...