刚开始学习,介绍先搁着~等理解透彻了再来写~~~   我是学习的mzry1992(UESTC_Izayoi ~)------http://www.mzry1992.com/blog/miao/kd%E6%A0%91.html 先去看mzry1992大牛博客里的讲解吧。。。   再附两篇论文:(看英文看得好爽。。。~@.@) 《An intoductory tutorial on kd-trees》  ★(里面就介绍了kd-tree和nearest neighbour algorithm(最近邻算法)、Q nearest neighbour(Q近邻)) 《Range Searching Using Kd-Tree.》    kd-tree入门题:     HDOJ 2966 In case of failure (最近邻,模板~)   查找平面点最近点的距离(此题中是距离的平方)


/*HDOJ 2966KD-Tree模板
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x, y) ( (x + y)>>1 )using namespace std;
typedef long long LL;//KD-Tree模板
const int N=100005;
LL res;
struct Point
{int x, y;        //点是二维的,此时是2D-Tree
};LL dist2(const Point &a, const Point &b)            //距离的平方
{return LL(a.x - b.x) * LL(a.x - b.x) + LL(a.y - b.y) * LL(a.y - b.y);
}bool cmpX(const Point &a, const Point &b)
{return a.x < b.x;
}
bool cmpY(const Point &a, const Point &b)
{return a.y < b.y;
}struct KDTree        //很崇拜这种销魂的建树方法啊~0.0~很抽象很强大------p数组已经代表了KD-Tree了,神马左右子树全省了,OOOOOrrz!!!……
{Point p[N];        //空间内的点int Div[N];        //记录区间是按什么方式划分(分割线平行于x轴还是y轴, ==1平行y轴切;==0平行x轴切)void build(int l, int r)            //记得先把p备份一下。{if (l > r)    return;int mid=MID(l, r);int minX, minY, maxX, maxY;minX = min_element(p + l, p + r + 1, cmpX)->x;minY = min_element(p + l, p + r + 1, cmpY)->y;maxX = max_element(p + l, p + r + 1, cmpX)->x;maxY = max_element(p + l, p + r + 1, cmpY)->y;Div[mid] = (maxX - minX >= maxY - minY);nth_element(p + l, p + mid, p + r + 1, Div[mid] ? cmpX : cmpY);build(l, mid - 1);build(mid+1, r);}void find(int l, int r, Point a)                //查找最近点的平方距离{if (l > r)    return;int mid = MID(l, r);LL dist = dist2(a, p[mid]);if (dist > 0)   //如果有重点不能这么判断res = min(res, dist);LL d = Div[mid] ? (a.x - p[mid].x) : (a.y - p[mid].y);int l1, l2, r1, r2;l1 = l , l2 = mid + 1;r1 = mid - 1, r2 = r;if (d > 0)swap(l1, l2), swap(r1, r2);find(l1, r1, a);if (d * d < res)find(l2, r2, a);}
};

  HDOJ 4347 The Closest M Points (Q近邻)   与上题不同的是,一是k维(这个好处理~),二是求最近的m个点而不单是最近点了。这个也好处理~递归查找时处理的时候采取如下策略:如果当前找到的点小于k个,那么两个区间都要处理。。否则根据当前找到的第k个点决定是否去另外一个区间,如果目标点到分界线的距离大于等于已经找到的第k远的点,那么就不用查找另一个分界了。。。更新答案可以用一个大小为k的堆去维护(一个最大堆,一旦超过k个点就把最大的扔掉)。。。


#include #include #include #include #include #include #include #include #include #include #include #include #define MID(x,y) ( (x + y)>>1 )using namespace std;typedef long long LL;//KD-Tree模板const int N=50005;struct Point{int x[5];LL dis;Point(){for (int i = 0; i < 5; i++)x[i] = 0;dis = 9223372036854775807LL;}friend bool operator < (const Point &a, const Point &b){return a.dis < b.dis;}};priority_queue  > res;LL dist2(const Point &a, const Point &b, int k)            //距离的平方,开根号很耗时,能不开就不开{LL ans = 0;for (int i = 0; i < k; i++)         //一开始这儿写的i < 5,WA了N次。。。原本以为只要初始值设0就无所谓,ans += (a.x[i] - b.x[i]) * (a.x[i] - b.x[i]);   //但发现Point有个全局变量,在多case下会出错。。。return ans;}int ddiv;bool cmpX(const Point &a, const Point &b){return a.x[ddiv] < b.x[ddiv];}struct KDTree        //很崇拜这种销魂的建树方法啊~0.0~很抽象很强大------p数组已经代表了KD-Tree了,神马左右子树全省了,OOOOOrrz!!!……{Point p[N];        //空间内的点int Div[N];        //记录区间是按什么方式划分(分割线平行于x轴还是y轴, ==1平行y轴切;==0平行x轴切)int k;          //维数int m;          //近邻int getDiv(int l, int r)        //寻找区间跨度最大的划分方式{map  ms;int minx[5],maxx[5];for (int i = 0; i < k; i++){ddiv = i;minx[i] = min_element(p + l, p + r + 1, cmpX)->x[i];maxx[i] = max_element(p + l, p + r + 1, cmpX)->x[i];ms[maxx[i] - minx[i]] = i;}map ::iterator pm = ms.end();pm--;return pm->second;}void build(int l, int r)            //记得先把p备份一下。{if (l > r)    return;int mid = MID(l,r);Div[mid] = getDiv(l,r);ddiv = Div[mid];nth_element(p + l, p + mid, p + r + 1, cmpX);build(l, mid - 1);build(mid + 1, r);}void findk(int l, int r, Point a)                //k(m)近邻,查找k近点的平方距离{if (l > r)    return;int mid = MID(l,r);LL dist = dist2(a, p[mid], k);if (dist >= 0){p[mid].dis = dist;res.push(p[mid]);while ((int)res.size() > m)res.pop();}LL d = a.x[Div[mid]] - p[mid].x[Div[mid]];int l1, l2, r1, r2;l1 = l , l2 = mid + 1;r1 = mid - 1, r2 = r;if (d > 0)swap(l1, l2), swap(r1, r2);findk(l1, r1, a);if ((int)res.size() < m || d*d < res.top().dis )findk(l2, r2, a);}};Point pp[N];KDTree kd;int main(){//    freopen("test.txt","r+",stdin);//    freopen("ans.txt","w+",stdout);int n;while(scanf("%d%d", &n, &kd.k)!=EOF){for (int i = 0; i < n; i++)for (int j = 0; j < kd.k; j++){scanf("%d", &pp[i].x[j]);kd.p[i] = pp[i];}kd.build(0, n - 1);int t;scanf("%d", &t);while(t--){Point a;for (int i = 0; i < kd.k; i++)scanf("%d", &a.x[i]);scanf("%d", &kd.m);kd.findk(0, n - 1, a);printf("the closest %d points are:\n", kd.m);Point ans[11];for (int i = 0; !res.empty(); i++){ans[i] = res.top();res.pop();}for (int i = kd.m - 1; i >= 0; i--){for (int j = 0; j < kd.k - 1; j++)printf("%d ", ans[i].x[j]);printf("%d\n", ans[i].x[kd.k - 1]);}}}return 0;}

转载于:https://www.cnblogs.com/AbandonZHANG/archive/2012/09/21/4114170.html

kd-Tree 【专题@AbandonZHANG】相关推荐

  1. PCL :K-d tree 2 结构理解

    K-d tree 基础思路:(先看之前的KNN思想,更容易理解) 导语:kd 树是一种二叉树数据结构,可以用来进行高效的 kNN 计算.kd 树算法偏于复杂,本篇将先介绍以二叉树的形式来记录和索引空间 ...

  2. PCL:k-d tree 1 讲解

    1.简介 kd-tree简称k维树,是一种空间划分的数据结构.常被用于高维空间中的搜索,比如范围搜索和最近邻搜索.kd-tree是二进制空间划分树的一种特殊情况.(在激光雷达SLAM中,一般使用的是三 ...

  3. k-d tree算法的研究

    By RaySaint 2011/10/12 动机 先前写了一篇文章<SIFT算法研究>讲了讲SIFT特征具体是如何检测和描述的,其中也提到了SIFT常见的一个用途就是物体识别,物体识别的 ...

  4. k-d tree树 近邻算法

    k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...

  5. K-d tree 算法

    转载的原文链接:http://www.cnblogs.com/eyeszjwang/articles/2429382.html 已经写得非常好了,非常清晰.只是在原文的基础上增加了一点解释,方便大家理 ...

  6. kd tree python 搜索

    海量数据最近邻查找可以用kd tree 目前理解,kd tree需要的数据维度相同,否则会出问题 kd tree实现:https://github.com/stefankoegl/kdtree 下面是 ...

  7. BZOJ 3489: A simple rmq problem(K-D Tree)

    Time Limit: 40 Sec  Memory Limit: 512 MB Submit: 2579  Solved: 888 [Submit][Status][Discuss] Descrip ...

  8. k-d tree算法

    k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...

  9. BZOJ4066:简单题(K-D Tree)

    Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格 ...

  10. BZOJ4520:[CQOI2016]K远点对(K-D Tree)

    Description 已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对. Input 输入文件第一行为用空格隔开的两个整数 N, K.接下来 N 行,每行两个整数 X,Y,表示一个点 的坐标 ...

最新文章

  1. Cocos Creator里localStorage的使用
  2. excel求和为什么是0_Excel教程:小小的N函数竟如此厉害
  3. 《数据科学家养成手册》第九章信息论
  4. Neo4j:空值如何工作?
  5. 右边菜单_AI基础教程65:使用文字菜单编辑文字(七)查找字体
  6. 金蝶k3财务接口_记录用友T+接口对接的心酸历程
  7. 从事前端多年,我是这样看待三大框架的
  8. 台式电脑连不上wifi怎么办
  9. html如何将设置文本效果,Word2013中通过设置文本效果格式来为文字添加特殊效果...
  10. python第三方库安装路径
  11. 在Win10上布置定时任务,运行Python脚本备份文件到FTP远程服务器
  12. 横向堆积柱状图(peak distribution)
  13. cf#644 div2 B. Boboniu Plays Chess
  14. 【风马一族_xml】xml编程
  15. 可以过滤网页中广告的插件Adblock Plus
  16. 2022北京最新八大员之(安全员)考试试题题库及答案
  17. 畜禽养殖智能环境监控系统
  18. 实验四 进程同步与通信(一)进程同步与互斥1
  19. (十六)【模电】(放大电路中的反馈)反馈的概念及判断
  20. Stack Overflow 的 HTTPS 化:漫漫长路的终点

热门文章

  1. Qt5.x解决报错main.cpp:1:10: fatal error: QApplication: No such file or directory问题
  2. 应用程式中夜间模式的Android DayNight主题
  3. aws lambda_在AWS Lambda上运行“ Hello World”
  4. 带有第三方工具的Spring Boot Initilizr
  5. 如何在Ubuntu 18.04上安装Elasticsearch Logstash Kibana(Elastic Stack)
  6. 人工智能发展中面临的问题有哪些?
  7. Python3基础——字典、其他常用操作
  8. Socket 编程实战
  9. 【原】React中,map出来的元素添加事件无法使用
  10. sql:Mysql create view,function,procedure