刚开始学习,介绍先搁着~等理解透彻了再来写~~~
我是学习的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 2966 KD-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 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 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 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() = 0; i--) { for (int j = 0; j来源:
https://www.cnblogs.com/AbandonZHANG/archive/2012/09/21/4113953.html