K-d деревья: алгоритм поиска ближайшего соседа

Вот мое понимание этого: 1. Проведите рекурсию вниз по дереву, взяв левое или правое поддерево в зависимости от того, будет ли ELEMENT лежать в левом или правом поддереве, если он существует. 2. Установите CURRENT_BEST в качестве первого достижимого конечного узла. 3. Во время рекурсии проверьте, находится ли ELEMENT ближе к разделяющей гиперплоскости, чем к CURRENT_BEST. Если это так, установите CURRENT_BEST в качестве текущего узла.

Это часть, которую я получил из Википедии и моего класса, а часть - нет. понять: 4. Проверить, не находится ли какой-либо узел в другом поддереве точки разделения, выделенной в 3., ближе к ELEMENT, чем точка разделения.

Я не понимаю, почему нам нужно делать 4., поскольку любая точка, которая может лежать в одном поддереве узла разбиения, обязательно должна быть ближе к узлу разбиения, чем к любой точке в другом поддереве.

Очевидно, что мое понимание алгоритма ошибочно, поэтому помощь будет принята с благодарностью.


person Kaiser Octavius    schedule 22.11.2012    source источник
comment
из какой статьи в Википедии вы получили эту информацию? Не могли бы вы дать ссылку в своем вопросе?   -  person didierc    schedule 22.11.2012
comment
@didierc - добавлено 3 года спустя   -  person Martin F    schedule 28.02.2016
comment
условие на шаге 3 - обратное?   -  person user352102    schedule 04.03.2020


Ответы (3)


Шаг 4 - это «else» на шаге 3, что вы делаете, если плоскость ближе, чем точка. Тот факт, что найденная вами точка будет находиться в том же прямоугольнике, что и точка, для которой вы ищете соседа, не означает, что она является ближайшей.

Представьте себе следующий сценарий: у вас есть две точки в вашем kD-дереве, A и B. A находится в середине его прямоугольника, а B находится чуть выше края, в разделенной области рядом с A. Если вы теперь выполните поиск для ближайшего соседа к точке C, которая находится рядом с B, но оказывается по другую сторону края и в области разделения A, ваша первая точка, которую вы выберете, будет A из-за начального поиска в глубину, который выбирает все будет в том же разделе, что и ваша точка поиска. Однако B на самом деле ближе, поэтому, даже если вы выбрали A, вам нужно проверить, ближе ли B, иначе ваше kD-Tree на самом деле не даст вам правильных результатов.

Хороший способ визуализировать это - нарисовать:

A-------------C--|--B

A - это первая точка, которую мы нашли в DFS, C - это наша точка, ближайший сосед которой мы хотим, B - фактический ближайший сосед, | это наш разделенный самолет.

Другой способ представить это - нарисовать круг с радиусом dist (A, C) вокруг точки C. ближе к C, чем A, поэтому их необходимо проверить. Если вы теперь найдете B, вы можете уменьшить радиус своего круга (потому что B ближе), чтобы меньше прямоугольников могло пересекаться, и как только вы проверите все прямоугольники, которые пересекаются с вашим кругом (уменьшив радиус вашего круга, как ваш найти более близких соседей) можно однозначно сказать, что более близких точек нет.

person jkflying    schedule 14.12.2012

Я написал базовую реализацию C ++ на github. У него есть как итеративная, так и рекурсивная версии.

person gvd    schedule 05.12.2012

person    schedule
comment
Этот алгоритм описывает построение k-d дерева без поиска ближайшего соседа. - person Jernej Jerin; 17.04.2013