数组实现最近邻搜索的核心是用一维坐标数组+索引数组模拟KD树,通过维度选择、快速选择中值、栈式剪枝搜索实现高效查询;K近邻则用最大堆维护候选集。

用数组实现最近邻搜索,核心是把高维点集组织成可快速剪枝的结构,而不是靠暴力遍历。关键不在“数组”本身,而在如何用数组高效承载KD树的构建与查询逻辑——它让空间划分、中值选取、递归搜索全部落在连续内存上,兼顾清晰性与可控性。
用一维数组存多维数据,避免对象开销
不为每个点创建独立对象,而是把所有坐标的同维度分量连续排布。例如1000个3维点,用长度为3000的float数组存储:
— 索引0~999存所有点的x坐标
— 索引1000~1999存所有点的y坐标
— 索引2000~2999存所有点的z坐标
再配一个int型索引数组(如indices[1000]),初始存0~999,建树时只重排这个索引数组,不动原始坐标数据。这样既节省内存,又避免指针跳转,缓存友好。
建树时动态选维+中值分割,靠索引数组完成
每轮递归建子树前,先扫描当前索引范围内各维度的坐标范围(max-min)或方差,选范围最大的维度作为本次分割轴;然后根据该维度的坐标值,对当前索引子数组做快速选择(QuickSelect)或部分排序,找到中位数对应的那个索引位置m;将m设为当前节点,左边索引段建左子树,右边建右子树。整个过程只操作索引数组,原始坐标数组全程只读。
最近邻搜索用栈模拟递归,配合距离上界剪枝
不用递归函数调用栈,改用显式stack存待访问节点的索引区间和深度。每次取栈顶,计算查询点到当前超矩形区域的最小可能距离(即各维度上投影距离的平方和)。如果该距离已大于当前已知最近距离,则跳过整棵子树。进入子节点前,优先走更靠近查询点的一侧;另一侧仅当超球体与分割超平面相交(即该侧可能含更近点)时才压栈。这样大幅减少无效访问。
K近邻扩展:固定大小最大堆维护候选集
要找k个最近点,维护一个容量为k的最大堆,堆顶是当前k个中最远的那个。每次遇到新点,若堆未满则入堆;若已满且新距离小于堆顶距离,则弹出堆顶、插入新点。搜索过程中,判断另一侧子树是否需访问的条件也升级为:查询点到该侧超矩形的最小距离










