Подходящий выбор структуры данных и алгоритма для быстрого поиска K-ближайшего соседа в 2D

У меня есть набор данных приблизительно 100 000 (X, Y) пар, представляющих точки в 2D-пространстве. Для каждого точка, я хочу найти ее k-ближайших соседей.

Итак, мой вопрос - какая структура данных / алгоритм будет подходящим выбором, предполагая, что я хочу абсолютно минимизировать общее время работы?

Я не ищу код-просто указатель на подходящий подход. Я немного обескуражен диапазоном вариантов, которые кажутся релевантными-quad-trees, R-деревья, KD-деревья и т. д.

Я думаю, что лучший подход-построить структуру данных, а затем запустить какой-то поиск K-ближайшего соседа для каждой точки. Однако, поскольку (А) я знаю точки заранее, и (б) я знаю, что должен выполнить поиск каждой точки ровно один раз, возможно, есть лучший подход?

дополнительные сведения:

  • так как я хочу свести к минимуму все время работы, мне все равно, если большая часть времени тратится на структуру против поиск.
  • пары (X, Y) довольно хорошо распределены, поэтому мы можем предположить почти равномерное распределение.

1 ответов


Если k относительно мало (

внутри каждого элемента сетки, точки должны быть отсортированы по одной координате (скажем, х). Начиная с выбранного элемента (найдите его с помощью bisection), пройдите по отсортированному списку, пока не найдете k элементов (опять же, если k мало, самый быстрый способ сохранить список k лучших хитов - это двоичная вставка сортировка, позволяя худшему совпадению упасть с конца при вставке; сортировка вставки обычно бьет все остальное примерно до 30 элементов на современном оборудовании). Продолжайте идти, пока ваш самый дальний ближайший сосед не будет ближе к вам, чем следующие точки от вас в x (т. е. не считая их y-смещения, поэтому не может быть никакой новой точки, которая может быть ближе, чем KTH-ближайший найденный до сих пор).

Если у вас еще нет k точек, или у вас есть k точек, но одна или несколько стенок элемента сетки ближе к вашей точке интереса, чем самая дальняя из k точек, добавьте соответствующие соседние элементы сетки в поиск.

Это должно дать вам представление что-то вроде O(N*k^2), с относительно низким постоянным фактором. Если k большой, то эта стратегия слишком упрощена, и вы должны выбрать алгоритм, который является линейным или лог-линейным в k, как KD-деревья могут быть.