Алгоритм Балабана — различия между версиями
(→Основы алгоритма) |
(→Время работы) |
||
Строка 215: | Строка 215: | ||
<tex>\forall v \in V \ |S_v'| \le a_v - b_v + |Int(D_v, S_v')|</tex>. | <tex>\forall v \in V \ |S_v'| \le a_v - b_v + |Int(D_v, S_v')|</tex>. | ||
|proof= | |proof= | ||
− | Утверждение напрямую вытекает из [[#lemma1|леммы]] | + | Утверждение напрямую вытекает из [[#lemma1|первой леммы]] и очевидного факта, что для любого множества <tex>S \subset S_0</tex>, количество концов отрезков, лежащих в полосе <tex>\langle a_v, b_v \rangle</tex>, меньше чем <tex>b_v - a_v</tex>. |
}} | }} | ||
Строка 226: | Строка 226: | ||
Утверждение напрямую вытекает из [[#lemma2|леммы №2]] и следующего отношения <tex>\sum_v (b_v - a_v) \le 2N \lceil logN + 1 \rceil</tex>. | Утверждение напрямую вытекает из [[#lemma2|леммы №2]] и следующего отношения <tex>\sum_v (b_v - a_v) \le 2N \lceil logN + 1 \rceil</tex>. | ||
}} | }} | ||
+ | |||
+ | Обозначим множество всех вершин рекурсивного дерева за <tex>RT</tex>. | ||
{{Теорема | {{Теорема | ||
Строка 233: | Строка 235: | ||
<tex>\sum_{v \in RT} |S_v| \le N \lceil 4logN + 5 \rceil + 2K</tex> | <tex>\sum_{v \in RT} |S_v| \le N \lceil 4logN + 5 \rceil + 2K</tex> | ||
|proof= | |proof= | ||
− | Для всех узлов, кроме корня <tex>r</tex> имеет место выражение <tex>|S_v| \le |S_{ft(v)}'|</tex>, следовательно <tex>\sum_{v \in RT} |S_v| \le |S_r| + \sum_{v \in RT \setminus r} |S_{ft(v)}| \le N + 2 \sum_{v \in V} | | + | Для всех узлов, кроме корня <tex>r</tex> имеет место выражение <tex>|S_v| \le |S_{ft(v)}'|</tex>, следовательно <tex>\sum_{v \in RT} |S_v| \le |S_r| + \sum_{v \in RT \setminus r} |S_{ft(v)}| \le N + 2 \sum_{v \in V} |S_v'| \le N \lceil 4 logN + 5 \rceil + 2K</tex>. |
}} | }} | ||
− | Начальная сортировка и инициализация множеств <tex>L_r</tex> и <tex>I_r</tex> может быть произведена за <tex>O(N logN)</tex> времени. Время работы функции <tex>TreeSearch</tex> является суммой длительностей всех его вызовов. Каждый вызов от внешних узлов добавляет к этой сумме <tex>O(|L_v| + |Int_{a, b}(L_v)|)</tex>. Для внутренних же узлов, время требуемое для | + | Начальная сортировка и инициализация множеств <tex>L_r</tex> и <tex>I_r</tex> может быть произведена за <tex>O(N logN)</tex> времени. Время работы функции <tex>TreeSearch</tex> является суммой длительностей всех его вызовов. Каждый вызов от внешних узлов добавляет к этой сумме <tex>O(|L_v| + |Int_{a, b}(L_v)|)</tex>. Для внутренних же узлов, время требуемое для поиска <tex>Loc(D_v, s)</tex> равно <tex>O(|I_v| log N)</tex>, а для остальных <tex>O(|S_v| + |Int(D_v, S_v')|)</tex>. Если мы все это сложим, то придем к выводу, что наш алгоритм работает за <tex>O(N log^2 N + K)</tex>. Заметим, что его скорость можно увеличить до <tex>O(N logN + K)</tex>, если не будем учитывать время нахождения <tex>Loc(D_v, s)</tex>. |
Соответственно в оптимальном алгоритме Балабана <tex>Loc(D_v, s)</tex> находится за <tex>O(1)</tex>. | Соответственно в оптимальном алгоритме Балабана <tex>Loc(D_v, s)</tex> находится за <tex>O(1)</tex>. |
Версия 17:40, 15 ноября 2013
Алгоритм Балабана — детерминированный алгоритм, позволяющий по множеству отрезков на плоскости получить множество точек, в которых эти отрезки пересекаются.
Содержание
Введение
Решение задачи по поиску множества пересечений отрезков является одной из главных задач вычислительной геометрии. Тривиальный детерминированный алгоритм имеет временную сложность [1] с оценкой сложности , в основе которого лежит метод заметающей прямой. Алгоритм, предложенный Чазелле и Едельсбруннером [2], имеет лучшую оценку , но в отличие от предыдущих методов требует квадратичной памяти. Оптимальный детерминированный алгоритм был предложен Балабаном [3] с временной оценкой сложности и памяти, где К - число пересекающихся отрезков. При количестве отрезков от 2000, и большому количеству пересечений целесообразно использовать алгоритм Балабана. Однако в результате громоздкости и высокой сложности реализации алгоритма, в большинстве практических задач используется алгоритм заметающей прямой Бентли-Оттмана.
, и его суть заключается в проверке попарного пересечения отрезков. Сложнее, но эффективнее алгоритм Бентли-ОттманаОсновные понятия
Введем некоторые обозначения. Пусть
Через обозначим вертикальную полосу, которая ограничена прямыми и , а через — отрезок с вершинами в точках с абсциссами и .
Рассмотрим взаимное расположение вертикальной полосы и отрезка .
Определение: |
Будем говорить, что отрезок - содержит(span) полосу | , с вершинами в точках с абсциссами и :
Определение: |
Два отрезка Для двух множеств отрезков и определим множество как . | и называются пересекающимися внутри полосы , если их точка пересечения лежит в пределах этой полосы.
Обозначения
и будут использоваться для описания подмножеств и , состоящих из пересекающихся пар отрезков в пределах полосы . Далее скобки используются для определения неупорядоченных множеств, а скобки используются для определения упорядоченных множеств.Введем отношение порядка на множестве отрезков
если оба отрезка пересекают вертикальную линию и точка пересечения этой прямой с отрезком лежит ниже точки пересечения с .
− любой отрезок из
− нет пересечений отрезков внутри лестницы;
− упорядочена по отношению .
Определение: |
Будем называть лестницу | полностью соотносимой множеству отрезков , если каждый отрезок из либо не пересекает полосу , либо пересекает хотя бы одну из ступенек из множества .
Лемма: |
Пусть лестница полностью соотносима множеству отрезков , где состоит из отрезков, пересекающих полосу , тогда ,где это число вершин отрезков из , находящихся в пределах полосы . |
Определение: |
Если точка | отрезка лежит между ступеньками и , тогда число называется местоположением на лестнице и обозначается как
Утверждение: |
Имея лестницу и множество отрезков , множество можно найти за время . Однако, если упорядочено отношением , где , тогда можно найти за время . |
Алгоритм
Введем несколько дополнительных функций, чтобы упростить основной алгоритм:
Split
Функция
разделяет входное множество отрезков , пересекающих некоторую полосу , на подмножества и так, что лестница полностью соотносима множеству отрезков .Пусть, где for do if отрезок не пересекает последний отрезок из внутри полосы и при этом содержит её then добавить в конец else добавить в конец
Эта функция работает за
времени.Search In Strip
Зная
мы можем найти и используя следующую рекурсивную функцию:if then return Найдем
Здесь,
это функция объединения множеств и , упорядоченных по отношению . Время выполнения эквивалентно сумме времён каждого её запуска. Очевидно, что время работы -той функции, будет равно , где это соответствующие наборы .Учитывая лемму, заключаем, что функция работает за .
Предположим, что все отрезки лежат в полосе лемме , таким образом, число дополнительных отрезков, появляющихся после разрезаний пропорционально числу найденных пересечений.
. Таким образом в самом начале у нас есть пара . Что же дальше происходит: множество распадается в подмножества и , после чего лестница становится полностью соотносимой множеству . Необходимо найти пересечения отрезков из и , затем, все пересечения в . Чтобы найти пересечения отрезков в , мы режем полосу и множество по вертикале на полосы , и множества , соответственно, где является медианой вершин отрезков между и . Затем мы рекурсивно вызываем функцию к парам и . Ключевым является тот факт, что согласноОсновы алгоритма
Давайте разберемся с алгоритмом более подробно:
Не умаляя общности, предположим, что все пересечения и вершины отрезков имеют разные абсциссы (в конечном счете, их можно будет отсортировать введением дополнительных свойств). Будем рассматривать целые координаты на промежутке
. Пусть и будут координатами вершин -того отрезка.Основная задача нашего алгоритма, это рекурсивная функция
. Соединим каждый вызов функции с узлом некоего двоичного дерева (далее рекурсивное дерево). Соответствующим узлом отметим все значения, множества и параметры вызова. Обозначим множество внутренних вершин за .Отсортируем вершин по координатам и найдем ;
if then отсортируем по отношению ; ; return; Разделим на и так, что лестница будет полностью соотносима множеству ; Найдем ; ; Разделим отрезки из на пересекающих полосу и полосу ; ; ;
Отсюда и дальше
, и означают, соответственно, левого сына, правого сына, и отцовскую вершину узла . Наша задача показать, что все операции с узлом происходят за , для этого возьмем во внимание, что (очевидно, что ).Функция
похожа на функцию . Основная разница заключается в том, что вызывает себя без изменения полосы, когда делит полосу на две части, после чего рекурсивно вызывает себя для них. Другое отличие заключается в том, что множество не упорядочено так же, как . В результате мы не можем напрямую использовать функцию для эффективного деления .Чтобы решить эту проблему, представим
как объединение трех множеств: множества упорядоченного по отношению , неупорядоченного множества , и множества упорядоченного по отношению . Расположим отрезки из , пересекающие границу во множество , отрезки пересекающие во множество , и внутренние отрезки во множество (пример на рисунке справа).Теперь мы можем вызвать функцию
для множества и построить за времени. Но мы натыкаемся на новую проблему: передавая множества , и , необходимо найти соответствующие множества сыновей узла .Неупорядоченные множества
и строятся легко. Множество будет найдено вызовом функции для нахождения в функции . Множество получается из за линейное время вставкой (если левая вершина отрезка) или удалением (если правая вершина отрезка) отрезка . Но как получить из , и без сортировки?Для листьев мы сделаем проверку вначале, и получим
из . Пусть и известны, и все сыновья узла - листья. Для начала запустим функцию и найдем и . Теперь мы должны найти , но мы не знаем и, соответственно, можем найти только . Применим к множеству и получим . Множество получается из вставкой или удалением отрезка . Применим к и найдем . Теперь можем продолжить вычисление и получим слиянием и .Конечная функция будет выглядеть так:
Отсортируем концов отрезков по абсциссе и найдем , где ; ; ; ;
if then ; return; ; ; Найдем ; ; Разделяем отрезки из внутренние для полосы во множество внутренние для полосы во множество ; if левый конец отрезка then вставить в else удалить из ; Найдем ; for do Найдем используя двоичный поиск; Найдем используя значения, полученные шагом выше; ;
Заметим, что нахождение
надо делать аккуратно, так как множества и могут иметь одни и те же отрезки (которые пересекают ). Мы нашли их пересечения с при поиске , и не должны вывести эти пересечения снова.Для начала рассчитаем место, необходимое для выполнения алгоритма. Алгоритм использует рекурсивную функцию
. Последовательность вызовов функции может занять память. Эта последовательность может быть представлена как путь корня рекурсивного дерева, до узла. Соответствующий вызов этого узла занимает памяти, каждый его "предок" занимает памяти, а остальные структуры используют . Очевидно, что любой путь от корня рекурсивного дерева до какого-то узла .В итоге для работы алгоритма требуется
памяти.Время работы
Лемма (#2): |
. |
Доказательство: |
Утверждение напрямую вытекает из первой леммы и очевидного факта, что для любого множества , количество концов отрезков, лежащих в полосе , меньше чем . |
Теорема (#1): |
Доказательство: |
Утверждение напрямую вытекает из леммы №2 и следующего отношения . |
Обозначим множество всех вершин рекурсивного дерева за
.Теорема (#2): |
Доказательство: |
Для всех узлов, кроме корня | имеет место выражение , следовательно .
Начальная сортировка и инициализация множеств
и может быть произведена за времени. Время работы функции является суммой длительностей всех его вызовов. Каждый вызов от внешних узлов добавляет к этой сумме . Для внутренних же узлов, время требуемое для поиска равно , а для остальных . Если мы все это сложим, то придем к выводу, что наш алгоритм работает за . Заметим, что его скорость можно увеличить до , если не будем учитывать время нахождения .Соответственно в оптимальном алгоритме Балабана
находится за .Примечания
Литература
Т.Вознюк, В.Терещенко — К построению эффективного решения задачи пересечения отрезков
Ф.Препарата, М.Шеймос — Вычислительная геометрия