Skip to content

Instantly share code, notes, and snippets.

@TrigonaMinima
Created April 4, 2017 14:31
Show Gist options
  • Save TrigonaMinima/620dcef1b270efd6a7f8cc78e475942f to your computer and use it in GitHub Desktop.
Save TrigonaMinima/620dcef1b270efd6a7f8cc78e475942f to your computer and use it in GitHub Desktop.
b-k tree
# http://signal-to-noise.xyz/post/bk-tree/
# to search nearest-neighbors of a query from the "metric space".
# distance should fulfill the 4 axioms of a metric.
from collections import deque
class BKTree:
def __init__(self, distance_func):
self._tree = None
self._distance_func = distance_func
def add(self, node):
if self._tree is None:
self._tree = (node, {})
return
current, children = self._tree
while True:
dist = self._distance_func(node, current)
target = children.get(dist)
if target is None:
children[dist] = (node, {})
break
current, children = target
def search(self, node, radius):
if self._tree is None:
return []
candidates = deque([self._tree])
result = []
while candidates:
candidate, children = candidates.popleft()
dist = self._distance_func(node, candidate)
if dist <= radius:
result.append((dist, candidate))
low, high = dist - radius, dist + radius
candidates.extend(c for d, c in children.items()
if low <= d <= high)
return result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment