【kd-tree】专题总结

本文详细介绍了KD树的数据结构及其构建与查询方法,重点讲解了如何通过KD树寻找k维空间中的最近邻点和最远邻点,并提供了完整的代码实现。

感谢orz神·小黑的指导

 

kd-tree就是用来计算若干维空间k近/远点的数(shou)据(suo)结(you)构(hua)

建树

假设题目是k维的点

第deep层就是用deep%k+1维把所有点分为两块

取deep%k+1维中位数的点做为当前子树的根节点

再把该维比这个点小的点扔到左子树 比这个点大的扔到右子树 递归处理

详见代码

 1 void Sort(ll l,ll r,ll k){ cmpp=k; sort(kd+l,kd+r+1,cmp); }
 2 ll build(ll l,ll r,ll deep){
 3     if (l==r){
 4         kd[l].lc=kd[r].rc=0;
 5         return l;
 6     }
 7     Sort(l,r,deep);
 8     ll mid=(l+r)/2;
 9     if (l<mid) kd[mid].lc=build(l,mid-1,deep%k+1);
10     else kd[mid].lc=0;
11     if (mid<r) kd[mid].rc=build(mid+1,r,deep%k+1);
12     else kd[mid].rc=0;
13     return mid;
14 }

 

查询

询问离点S的前m近点 说它是搜索优化就是因为这里- -

维护大根堆记录答案 当元素个数小于m时直接push

反正判断有木有 比最大值小 有就pop再push

当搜索当t点是先用该点到S的距离维护堆

再判断如果S的deep%k+1维 比t点该维小就先搜索左子树 否则搜索右子树

搜索完一颗子树后 判断如果S到t点deep%k+1维的距离就≥ans显然继续搜索没用 就不继续搜索 否则搜索另一颗子树

代码

 1 void push(ll t){
 2     ll dis=getdis(S,poi[t]);
 3     if (size==m){
 4         if (dis>que.top().dis) return;
 5         else{
 6             que.pop();
 7             que.push(info(dis,t));
 8         }
 9     }else{
10         ++size;
11         que.push(info(dis,t));
12     }
13 }
14 void makeans(ll t,ll deep){
15     if (!t) return;
16     push(kd[t].t);
17     if (S.d[deep]<=kd[t].p.d[deep]){
18         makeans(kd[t].lc,deep%k+1);
19         if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].rc,deep%k+1);
20     }else{
21         makeans(kd[t].rc,deep%k+1);
22         if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].lc,deep%k+1);
23     }
24 }

 

最远点

这里讲的都是m近点- - 

如果是m远点其实是差不多的 只是维护的东西不太一样

需要维护每维的min和max

询问的时候基本同理yy下即可

 

求k位距离S的m近点代码

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <queue>
  4 typedef long long ll;
  5 using namespace std;
  6 const ll N=50001;
  7 struct inpo{
  8     ll d[6];
  9 }poi[N],S,ans[11];
 10 struct inkd{
 11     ll t,lc,rc;
 12     inpo p;
 13     inkd(const ll a=0,const ll b=0,const ll c=0):
 14         t(a),lc(b),rc(c){}
 15 }kd[N];
 16 struct info{
 17     ll dis,t;
 18     info(const ll a=0,const ll b=0):
 19         dis(a),t(b){}
 20 };
 21 priority_queue <info> que;
 22 ll root,n,k,m,t,cmpp,size;
 23 inline bool operator <(info a,info b){ return a.dis<b.dis; }
 24 inline bool cmp(inkd a,inkd b){ return a.p.d[cmpp]<b.p.d[cmpp]; }
 25 void Sort(ll l,ll r,ll k){ cmpp=k; sort(kd+l,kd+r+1,cmp); }
 26 ll sqr(ll x){ return x*x; }
 27 ll getdis(inpo a,inpo b){
 28     ll res=0;
 29     for (ll i=1;i<=k;i++) res+=sqr(a.d[i]-b.d[i]);
 30     return res;
 31 }
 32 ll build(ll l,ll r,ll deep){
 33     if (l==r){
 34         kd[l].lc=kd[r].rc=0;
 35         return l;
 36     }
 37     Sort(l,r,deep);
 38     ll mid=(l+r)/2;
 39     if (l<mid) kd[mid].lc=build(l,mid-1,deep%k+1);
 40     else kd[mid].lc=0;
 41     if (mid<r) kd[mid].rc=build(mid+1,r,deep%k+1);
 42     else kd[mid].rc=0;
 43     return mid;
 44 }
 45 void push(ll t){
 46     ll dis=getdis(S,poi[t]);
 47     if (size==m){
 48         if (dis>que.top().dis) return;
 49         else{
 50             que.pop();
 51             que.push(info(dis,t));
 52         }
 53     }else{
 54         ++size;
 55         que.push(info(dis,t));
 56     }
 57 }
 58 void makeans(ll t,ll deep){
 59     if (!t) return;
 60     push(kd[t].t);
 61     if (S.d[deep]<=kd[t].p.d[deep]){
 62         makeans(kd[t].lc,deep%k+1);
 63         if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].rc,deep%k+1);
 64     }else{
 65         makeans(kd[t].rc,deep%k+1);
 66         if (size<m || que.top().dis>sqr(S.d[deep]-kd[t].p.d[deep])) makeans(kd[t].lc,deep%k+1);
 67     }
 68 }
 69 int main(){
 70     freopen("hdu4347.in","r",stdin);
 71     freopen("hdu4347.out","w",stdout);
 72     while (~scanf("%I64d%I64d",&n,&k)){
 73         for (ll i=1;i<=n;i++){
 74             for (ll j=1;j<=k;j++) scanf("%I64d",&poi[i].d[j]);
 75             kd[i].t=i,kd[i].p=poi[i];
 76         }
 77         root=build(1,n,1);
 78         scanf("%I64d",&t);
 79         for (;t;t--){
 80             size=0;
 81             for (ll i=1;i<=k;i++) scanf("%I64d",&S.d[i]);
 82             scanf("%I64d",&m);
 83             printf("the closest %I64d points are:\n",m);
 84             makeans(root,1);
 85             for (ll i=1;i<=m;i++){
 86                 ans[i]=poi[que.top().t];
 87                 que.pop();
 88             }
 89             for (ll i=m;i;i--){
 90                 for (ll j=1;j<=k;j++){
 91                     printf("%I64d",ans[i].d[j]);
 92                     if (j<k) printf(" ");
 93                 }
 94                 puts("");
 95             }
 96         }
 97     }
 98     fclose(stdin);
 99     fclose(stdout);
100 }
View Code

 

转载于:https://www.cnblogs.com/g-word/p/3729528.html

内容概要:本文详细阐述了车载以太网通信栈中两个核心模块——以太网接口(EthIf)与以太网驱动(Eth)的功能需求与技术规范。重点介绍了EthIf在上下层协议间的数据转发、硬件抽象、VLAN支持、PDU配置、队列调度、睡眠管理及性能计数器等方面的设计要求;同时深入描述了Eth模块在硬件初始化、工作模式切换、时间戳支持、DMA传输、流量整形与调度、帧抢占等底层驱动功能的技术实现要点。整体围绕车载高可靠性、低延迟、可配置性强的通信需求展开,体现了现代汽车电子架构对高性能网络通信的支持能力。; 适合人群:从事汽车电子、车载网络通信、ECU开发的工程师,尤其是熟悉AUTOSAR架构并希望深入了解以太网协议栈底层机制的研发人员;具备一定嵌入式系统和网络通信基础的技术人员。; 使用场景及目标:①用于设计和实现符合车规级要求的以太网通信栈;②理解EthIf与Eth在车载网络中的角色分工与协作机制;③掌握中断/轮询模式、VLAN处理、时间同步、流量调度、帧抢占等关键技术在实际系统中的应用;④支持高实时性应用场景如自动驾驶、多传感器融合等的网络架构设计。; 阅读建议:建议结合AUTOSAR标准文档及相关硬件手册进行对照学习,重点关注模块接口定义与状态机行为,结合实际项目需求进行配置与验证,并注意软硬件协同设计中的时序与资源管理问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值