首页 > 代码库 > kd tree学习 (最近邻域查询)
kd tree学习 (最近邻域查询)
https://zhuanlan.zhihu.com/p/22557068
http://blog.csdn.net/zhjchengfeng5/article/details/7855241
KD树在算法竞赛中主要用来做各种各样的平面区域查询,包含则累加直接返回,相交则继续递归,相离的没有任何贡献也直接返回。可以处理圆,三角形,矩形等判断起来相对容易的平面区域内的符合加法性质的操作。
比如查询平面内欧几里得距离最近的点的距离。
kdtree其实有点像搜索,暴力+剪枝。
每次从根结点向下搜索,并进行剪枝操作,判断是否有必要继续搜索。
它是通过横一刀,竖一刀,横一刀再竖一刀将平面进行分割,建立二叉树。
建树的复杂度是O(nlogn), 每次用nth_element()在线性时间内取出中位数。 T(n) = 2T(n/2) + O(n) = O(nlogn)
查询复杂度呢? 据第二个链接的博客说最坏是O( sqrt(n) ) 的。并不会分析查询复杂度。
HDU2966 裸kdtree
题意:给平面图上N(1 ≤ N ≤100000)个点,对每个点,找到其他 欧几里德距离 离他最近的点,输出他们之间的距离。保证没有重点。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 #define N 200010 5 const ll inf = 1e18; 6 int n,i,id[N],root,cmp_d; 7 int x, y; 8 struct node{int d[2],l,r,Max[2],Min[2],val,sum,f;}t[N]; 9 bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];} 10 void umax(int&a,int b){if(a<b)a=b;} 11 void umin(int&a,int b){if(a>b)a=b;} 12 void up(int x){ 13 if(t[x].l){ 14 umax(t[x].Max[0],t[t[x].l].Max[0]); 15 umin(t[x].Min[0],t[t[x].l].Min[0]); 16 umax(t[x].Max[1],t[t[x].l].Max[1]); 17 umin(t[x].Min[1],t[t[x].l].Min[1]); 18 } 19 if(t[x].r){ 20 umax(t[x].Max[0],t[t[x].r].Max[0]); 21 umin(t[x].Min[0],t[t[x].r].Min[0]); 22 umax(t[x].Max[1],t[t[x].r].Max[1]); 23 umin(t[x].Min[1],t[t[x].r].Min[1]); 24 } 25 } 26 int build(int l,int r,int D,int f){ 27 int mid=(l+r)>>1; 28 cmp_d=D,std::nth_element(t+l,t+mid,t+r+1,cmp); 29 id[t[mid].f]=mid; 30 t[mid].f=f; 31 t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0]; 32 t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1]; 33 //t[mid].val=t[mid].sum=0; 34 if(l!=mid)t[mid].l=build(l,mid-1,!D,mid);else t[mid].l=0; 35 if(r!=mid)t[mid].r=build(mid+1,r,!D,mid);else t[mid].r=0; 36 return up(mid),mid; 37 } 38 39 ll dis(ll x1, ll y1, ll x, ll y) { 40 ll xx = x1-x, yy = y1-y; 41 return xx*xx+yy*yy; 42 } 43 ll dis(int p, ll x, ll y){//估价函数, 以p为子树的最小距离 44 ll xx = 0, yy = 0; 45 if(t[p].Max[0] < x) xx = x-t[p].Max[0]; 46 if(t[p].Min[0] > x) xx = t[p].Min[0]-x; 47 if(t[p].Max[1] < y) yy = y-t[p].Max[1]; 48 if(t[p].Min[1] > y) yy = t[p].Min[1]-y; 49 return xx*xx+yy*yy; 50 } 51 ll ans; 52 void query(int p){ 53 ll dl = inf, dr = inf, d = dis(t[p].d[0], t[p].d[1], x, y); 54 if(d) ans = min(ans, d); 55 56 if(t[p].l) dl = dis(t[p].l, x, y); 57 if(t[p].r) dr = dis(t[p].r, x, y); 58 if(dl < dr){ 59 if(dl < ans) query(t[p].l); 60 if(dr < ans) query(t[p].r); 61 } 62 else { 63 if(dr < ans) query(t[p].r); 64 if(dl < ans) query(t[p].l); 65 } 66 } 67 68 int main(){ 69 int T; scanf("%d", &T); 70 while(T--){ 71 scanf("%d", &n); 72 for(int i = 1; i <= n; i++){ 73 scanf("%d%d", &t[i].d[0], &t[i].d[1]); 74 t[i].f = i; 75 } 76 int rt = build(1, n, 0, 0); 77 for(int i = 1; i <= n; i++){ 78 ans = inf; 79 x = t[ id[i] ].d[0], y = t[ id[i] ].d[1]; 80 query(rt); 81 printf("%lld\n", ans); 82 } 83 } 84 return 0; 85 }
kd tree学习 (最近邻域查询)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。