上一讲我们讲过,许多系统对于 GeoHash 的底层实现,其实都是使用二进制进行存储和计算的。而二进制区域编码的生成过程,就是一个逐渐二分空间的过程,经过二分后的区域之间是有层次关系的。如果我们把这个过程画下来,它就很像我们之前讲过的树形结构。
因此,我们可以尝试用树形结构来进行索引。这里,我们就要引入一个新的数据结构 四叉树 了。四叉树的树根节点代表了整个空间,每个节点的四个分叉分别表示四个子空间。其中,树根和中间节点不存储数据,只记录分叉指针。而数据只记录在最小的区域,也就是叶子节点上。
如果我们从根节点开始,不停地四分下去,直到每个分支的叶子节点都是最小粒度区域。那这样构建出来的四叉树,每个节点都有四个子节点,就叫作 满四叉树。
对于满四叉树的每个节点,我们都可以编号。换句话说,我们可以按 00、01、10、11 的编号,来区分满四叉树的四个子节点。这样一来,只要我们从根节点遍历到叶子节点,然后将路径上每个节点的编号连起来,那最后得到的编码就是这个叶子节点所代表的区域编码。
好了,现在我们知道了四叉树的结构和特点了,那我们怎么利用它完成自动调整范围的 Top K 检索呢?下面,我们通过一个例子来看看。
假设一个人所属的最小区域编码是 0110,那我们在检索的时候,就以 0110 为 Key,沿着四叉树的对应分支去寻找相应的区域,查询路径为 01-10。如果查找到了叶子节点,并且返回的结果大于 k 个,就可以直接结束检索。如果返回结果不足 k 个,我们就得递归返回到上一层的父节点,然后以这整个父节点的区域编码为目标进行检索。这样,我们就避免了要再次从树根检索到父节点的开销,从而提升了检索效率。