scipy
Перво-наперво: существуют уже существующие алгоритмы для таких вещей, как дерево kd .Scipy имеет реализацию Python cKDtree , которая может найти все точки в данном диапазоне.
Бинарный поиск
В зависимости от того, что вы делаете, реализация чего-то подобного можетбыть нетривиальнымКроме того, создание дерева является довольно сложным (возможно, с большими накладными расходами), и вы можете избежать простого взлома, который я использовал ранее:
- Вычислить PCA набора данных,Вы хотите повернуть набор данных так, чтобы наиболее значимое направление было первым, а ортогональное (менее большое) второе направление - ну, во-вторых, вторым.Вы можете пропустить это и просто выбрать X или Y, но это вычислительно дешево и обычно легко реализуемо.Если вы просто выберите X или Y, выберите направление с большей дисперсией.
- Сортируйте точки по главному направлению (назовите это направление X).
- Чтобы найти ближайшего соседа данногоpoint, найдите индекс точки, ближайшей к X, с помощью бинарного поиска (если точка уже находится в вашей коллекции, возможно, вы уже знаете этот индекс и вам не нужен поиск).Итеративно смотрите на следующую и предыдущую точки, сохраняя наилучшее совпадение и его расстояние от точки поиска.Вы можете перестать смотреть, когда разница в X больше или равна расстоянию до наилучшего совпадения (на практике обычно очень мало точек).
- Чтобы найти все точки в данном диапазоне, выполнитетак же, как в шаге 3, за исключением того, что не останавливайтесь, пока разница в X не превысит диапазон.
По сути, вы выполняете предварительную обработку O (N log (N)), и для каждой точки примерно o(sqrt (N)) - или больше , если распределение ваших очков плохое.Если точки распределены примерно равномерно, число точек ближе к X, чем к ближайшему соседу, будет порядка квадратного корня из N. Это менее эффективно, если в пределах вашего диапазона много точек, но никогда не намного хуже, чем грубая сила.
Одним из преимуществ этого метода является то, что он все исполняемый при очень небольшом распределении памяти и в основном может быть выполнен с очень хорошей локализацией памяти, что означает, что он работает довольно хорошо, несмотря на очевидные ограничения.
Триангуляция Делоне
Другая идея: Триангуляция Делоне может сработать.Для триангуляции Делоне указано, что ближайший сосед любой точки является смежным узлом.Интуиция заключается в том, что во время поиска вы можете поддерживать кучу (приоритетную очередь) на основе абсолютного расстояния от точки запроса.Выберите ближайшую точку, убедитесь, что она находится в диапазоне, и, если это так, добавьте всех ее соседей.Я подозреваю , что невозможно пропустить какие-либо моменты, подобные этой, но вам нужно более внимательно изучить это, чтобы быть уверенным ...