Ортогональный поиск — различия между версиями
| Glukos (обсуждение | вклад)  (→Прошитые отсортированные массивы) | Glukos (обсуждение | вклад)   (→Сбалансированное дерево поиска) | ||
| Строка 32: | Строка 32: | ||
| Каждая из функций <tex>range{\_}search(y_{min}, y_{max})</tex> будет работать в худшем случае за <tex>O(\log n)</tex>, отсюда получаем итоговое время выполнения запроса <tex>O(\log^2 n)</tex>. Что касается памяти, то в сбалансированном дереве поиска <tex>O(\log n)</tex> слоев, а каждый слой содержит массивы, содержащие в сумме ровно <tex>n</tex> точек, соответственно вся структура в целом занимает <tex>O(n\log n)</tex> памяти. | Каждая из функций <tex>range{\_}search(y_{min}, y_{max})</tex> будет работать в худшем случае за <tex>O(\log n)</tex>, отсюда получаем итоговое время выполнения запроса <tex>O(\log^2 n)</tex>. Что касается памяти, то в сбалансированном дереве поиска <tex>O(\log n)</tex> слоев, а каждый слой содержит массивы, содержащие в сумме ровно <tex>n</tex> точек, соответственно вся структура в целом занимает <tex>O(n\log n)</tex> памяти. | ||
| − | Такую структуру данных можно при необходимости обобщить на случай большей размерности. Пусть у нас есть множество точек из <tex> | + | Такую структуру данных можно при необходимости обобщить на случай большей размерности. Пусть у нас есть множество точек из <tex>p</tex>-мерного пространства, каждая из которых представляется как <tex>n</tex> координатных чисел: <tex>(\xi_1, \xi_2, ... , \xi_p)</tex>. Тогда, строя дерево поиска по координате <tex>\xi_i</tex>, в каждой вершине будем хранить другое дерево поиска с ключом <tex>\xi_{i+1}</tex>, составленное из точек, лежащих в соответствующем поддереве. В дереве поиска, составленном по предпоследней координате <tex>\xi_{p-1}</tex>, уже не будет необходимости хранить в каждой вершине целое дерево, поскольку при переходе на последнюю координату <tex>\xi_{p}</tex> дальнейший поиск производиться не будет, поэтому в вершинах будем хранить массивы, так же, как и в двумерном случае. Оценим занимаемую память и время запроса: при добавлении следующей координаты асимптотика обеих величин умножается на  <tex>\log n</tex>. Отсюда, получаем оценку <tex>O(\log^{p} n)</tex> на время запроса и <tex>O(n\log^{p-1} n)</tex> на занимаемую память. | 
| Такой же результат можно получить с помощью [[Сжатое многомерное дерево отрезков|сжатого многомерного дерева отрезков]]. | Такой же результат можно получить с помощью [[Сжатое многомерное дерево отрезков|сжатого многомерного дерева отрезков]]. | ||
Версия 19:47, 19 мая 2012
Содержание
Простейший случай
Пусть дана прямая с точками на ней и отрезок. Точки даны в отсортированном порядке. Необходимо указать, какие из изначальных точек лежат на этом отрезке.
Данная задача решается с помощью функций из STL - upper_bound и lower_bound.
lower_bound возвращает итератор на первый элемент, больший либо равный данного. 
upper_bound возвращает итератор на первый элемент множества со значением, большим данного.
Рассмотрим на примере:
Код реализации:
template<class RauIter, class OutIter, class Scalar> OutIter range_search(RauIter p, RauIter q, OutIter out)
{
   return std::copy(lower_bound(p, q, l), upper_bound(p, q, r), out);
}
Сбалансированное дерево поиска
Переходим к двумерному случаю. Пусть дано некоторое множество точек на плоскости. Нам необходимо ответить, какие именно из них лежат в некотором заданном прямоугольнике.
Для этого возьмем любое сбалансированное дерево поиска и наполним его точками из множества. В качестве ключа будет использоваться -координата точки. Теперь модернизируем дерево: в каждой вершине дерева будем хранить отсортированный по -координате массив точек, которые содержатся в соответствующем поддереве. В такой структуре данных поиск точек в заданном прямоугольнике будет выглядеть следующим образом:
- Выберем из дерева поиска те точки, -координата которых лежит в интервале . Сделаем это точно так же, как делается запрос сверху в дереве отрезков. Из аналогии с деревом отрезков следует, что мы ответ мы получим в виде поддеревьев дерева поиска.
- Для каждого из полученных поддеревьев обратимся к массиву содержащихся в нем точек и запустим от него приведенную выше функцию . Все полученные таким образом точки и будут составлять ответ.
TODO: запилить красивую и понятную картинку
Каждая из функций будет работать в худшем случае за , отсюда получаем итоговое время выполнения запроса . Что касается памяти, то в сбалансированном дереве поиска слоев, а каждый слой содержит массивы, содержащие в сумме ровно точек, соответственно вся структура в целом занимает памяти.
Такую структуру данных можно при необходимости обобщить на случай большей размерности. Пусть у нас есть множество точек из -мерного пространства, каждая из которых представляется как координатных чисел: . Тогда, строя дерево поиска по координате , в каждой вершине будем хранить другое дерево поиска с ключом , составленное из точек, лежащих в соответствующем поддереве. В дереве поиска, составленном по предпоследней координате , уже не будет необходимости хранить в каждой вершине целое дерево, поскольку при переходе на последнюю координату дальнейший поиск производиться не будет, поэтому в вершинах будем хранить массивы, так же, как и в двумерном случае. Оценим занимаемую память и время запроса: при добавлении следующей координаты асимптотика обеих величин умножается на . Отсюда, получаем оценку на время запроса и на занимаемую память.
Такой же результат можно получить с помощью сжатого многомерного дерева отрезков.
Прошитые отсортированные массивы
Для ускорения запроса можно "прошить" дерево поиска, а именно: каждый элемент массива, сохраненного в какой-либо вершине, соединить с элементами массивов, сохраненных в вершинах-детях. Соединять будем по следующему принципу: элемент массива-предка соединим с элементами и каждого массива-ребенка. Тогда для выполнения завершающей фазы поиска нам достаточно будет посчитать и только на массиве, привязанному к корню дерева. Для получения границ на других массивах можно будет просто спуститься по ссылкам от массива-предка за . Таким образом, поиск теперь будет выполняться за , где — размерность пространства.


