KD 树对于低维度 (D<20) 的近邻搜索非常快, 当 D 增长到很大时, 效率变低;这就是所谓的 “维度灾难” 的一种体现;
KD 树只能处理欧式距离;为了解决 KD 树在高维上效率低下的问题, ball 树 应运而生,同时 Ball tree 可处理一般的距离;
构建
空间中散落着很多个点.
- 把整个空间当作一个大簇.
- 找到距离最远的两个点 a 和 b , 叫做 观测点(请记住, 最后面要考) , 以它们为种子.
- 其余的簇内点 s 分别计算与 a 和 b 的距离, 离 a 近就归到 a 的子簇, 对 b 同理.
- 该找圆心和半径了, 这涉及另一个问题: 给一堆点, 怎么找到最小半径和圆心?最小圆覆盖问题算法
用它解出的圆不会超出父类圆的范围, 如果超出了会增加不少麻烦, 因为超出部分必没有属于该簇的点, 还容易在搜索时被干扰, 增加搜索量. - 上一步画好了圆, 就可以根据它们再分. 分别以两个圆重复1~4步, 直到只剩一个点, 就作为叶节点存储下来.
检索
使用ball tree时,先自上而下找到包含target的叶子结点(c, r),从此结点中找到离它最近的观测点。这个距离就是最近邻的距离的上界。检查它的兄弟结点中是否包含比这个上界更小的观测点。
方法是:如果目标点距离兄弟结点的圆心的距离 > 兄弟节点所在的圆半径 + 前面的上界的值,则这个兄弟结点不可能包含所要的观测点。否则,检查这个兄弟结点是否包含符合条件的观测点。
参考:
https://blog.csdn.net/qq_39006282/article/details/103290737