Подходящий выбор структуры данных и алгоритма для быстрого поиска 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-деревья могут быть.