Алгоритм Балабана — различия между версиями
(→Основной алгоритм: Приподнял картинку) |
|||
Строка 147: | Строка 147: | ||
<tex>TreeSearch(S_{rs}(v), c, b)</tex>; | <tex>TreeSearch(S_{rs}(v), c, b)</tex>; | ||
<tex>\}</tex> | <tex>\}</tex> | ||
+ | |||
+ | [[Файл:Balaban_pic_2.png|280px|thumb|right|<tex>S_v = (s_1, s_2, s_3, s_4, s_5)</tex>, <tex>L_v = (s_1, s_3)</tex>, <tex>R_v = (s_3, s_4)</tex>, <tex>I_v = (s_2, s_5)</tex>]] | ||
Отсюда и дальше <tex>ls(v)</tex>, <tex>rs(v)</tex> и <tex>ft(v)</tex> означают, соответственно, левого сына, правого сына, и отцовскую вершину узла <tex>v</tex>. | Отсюда и дальше <tex>ls(v)</tex>, <tex>rs(v)</tex> и <tex>ft(v)</tex> означают, соответственно, левого сына, правого сына, и отцовскую вершину узла <tex>v</tex>. | ||
Наша задача показать, что все операции с узлом <tex>v</tex> происходят за <tex>O(|S_v) + |Int(D_v, S_v')| + (a_v - b_v)logN)</tex>, и чтобы показать это, возьмем во внимание, что <tex>\sum_v |S_v| = O(N \cdot logN + K)</tex> (очевидно, что <tex>\sum_v |Int(D_v, S_v')| \le K</tex>). | Наша задача показать, что все операции с узлом <tex>v</tex> происходят за <tex>O(|S_v) + |Int(D_v, S_v')| + (a_v - b_v)logN)</tex>, и чтобы показать это, возьмем во внимание, что <tex>\sum_v |S_v| = O(N \cdot logN + K)</tex> (очевидно, что <tex>\sum_v |Int(D_v, S_v')| \le K</tex>). | ||
− | |||
− | |||
Функция <tex>TreeSearch</tex> похожа на функцию <tex>SearchInStrip</tex>. Основная разница заключается в том, что <tex>SearchInStrip</tex> вызывает себя без изменения полосы, когда <tex>TreeSearch</tex> делит полосу на две части, после чего рекурсивно вызывает себя для них. Другое отличие заключается в том, что множество <tex>S_v</tex> не упорядочено так же, как <tex>L</tex>. В результате мы не можем напрямую использовать функцию <tex>Split</tex> для эффективного деления <tex>S_v</tex>. | Функция <tex>TreeSearch</tex> похожа на функцию <tex>SearchInStrip</tex>. Основная разница заключается в том, что <tex>SearchInStrip</tex> вызывает себя без изменения полосы, когда <tex>TreeSearch</tex> делит полосу на две части, после чего рекурсивно вызывает себя для них. Другое отличие заключается в том, что множество <tex>S_v</tex> не упорядочено так же, как <tex>L</tex>. В результате мы не можем напрямую использовать функцию <tex>Split</tex> для эффективного деления <tex>S_v</tex>. | ||
Чтобы решить эту проблему, представим <tex>S_v</tex> как объединение трех множеств: | Чтобы решить эту проблему, представим <tex>S_v</tex> как объединение трех множеств: | ||
− | множества <tex>L_v</tex> упорядоченного по отношению <tex><_a</tex>, неупорядоченного множества <tex>I_v</tex>, и множества <tex>R_v</tex> упорядоченного по отношению <tex><_b</tex>. Расположим отрезки из <tex>S_v</tex>, пересекающие границу <tex>x = a</tex> во множество <tex>L_v</tex>, отрезки пересекающие <tex>x = b</tex> во множество <tex>R_v</tex>, и внутренние отрезки во множество <tex>I_v</tex>. | + | множества <tex>L_v</tex> упорядоченного по отношению <tex><_a</tex>, неупорядоченного множества <tex>I_v</tex>, и множества <tex>R_v</tex> упорядоченного по отношению <tex><_b</tex>. Расположим отрезки из <tex>S_v</tex>, пересекающие границу <tex>x = a</tex> во множество <tex>L_v</tex>, отрезки пересекающие <tex>x = b</tex> во множество <tex>R_v</tex>, и внутренние отрезки во множество <tex>I_v</tex> (пример на рисунке справа). |
==Примечания== | ==Примечания== |
Версия 21:54, 14 ноября 2013
Алгоритм Балабана — детерминированный алгоритм, позволяющий по множеству отрезков на плоскости получить множество точек, в которых эти отрезки пересекаются.
Содержание
Введение
Решение задачи по поиску множества пересечений отрезков является одной из главных задач вычислительной геометрии. Тривиальный детерминированный алгоритм имеет временную сложность [1] с оценкой сложности , в основе которого лежит метод заметающей прямой. Алгоритм, предложенный Чазелле и Едельсбруннером [2], имеет лучшую оценку , но в отличие от предыдущих методов требует квадратичной памяти. Оптимальный детерминированный алгоритм был предложен Балабаном [3] с временной оценкой сложности и памяти, где К - число пересекающихся отрезков. При количестве отрезков равным 2000 и большому количеству пересечений целесообразно использовать алгоритм Балабана. Однако в результате громоздкости и высокой сложности реализации алгоритма в большинстве практических задач используется алгоритм заметающей прямой Бентли-Оттмана.
, и его суть заключается в проверке попарного пересечения отрезков. Сложнее, но эффективнее алгоритм Бентли-ОттманаОсновные понятия
Введем некоторые обозначения. Пусть
Через обозначим вертикальную полосу, которая ограничена прямыми и , а через — отрезок с вершинами в точках с абсциссами и .
Рассмотрим взаимное расположение вертикальной полосы и отрезка .
Определение: |
Будем говорить, что отрезок - содержит(span) полосу | , с вершинами в точках с абсциссами и :
Определение: |
Два отрезка Для двух множеств отрезков и определим множество как . | и называются пересекающимися внутри полосы , если их точка пересечения лежит в пределах этой полосы.
Обозначения
и будут использоваться для описания подмножеств и , состоящих из пересекающихся пар отрезков в пределах полосы . Далее скобки используются для определения неупорядоченных наборов, а скобки используются для определения упорядоченных множеств.Введем отношение порядка на множестве отрезков
если оба отрезка пересекают вертикальную линию и точка пересечения этой прямой с отрезком лежит ниже точки пересечения с .
− любой отрезок из
− нет пересечений отрезков внутри лестницы;
− упорядочена по отношению .
Определение: |
Будем называть лестницу | полностью соотносимой множеству отрезков , если каждый отрезок из либо не пересекает полосу , либо пересекает хотя бы одну из ступенек из множества .
Лемма: |
Если лестница полностью соотносима множеству отрезков , где состоит из отрезков, пересекающих полосу , тогда ,где это число вершин отрезков , находящихся в пределах полосы . |
Определение: |
Если точка | отрезка лежит между ступеньками и , тогда число называется местоположением на лестнице и обозначается как
Утверждение: |
Имея лестницу и множество отрезков , множество можно найти за время . Однако, если упорядочено отношением , где , тогда можно найти за время . |
Алгоритм
Введем несколько дополнительных функций, чтобы упростить основной алгоритм:
Split
Функция
разделяет входное множество отрезков , пересекающих некоторую полосу , на подмножества и так, что лестница полностью соотносима множеству отрезков .Пусть, где for do if отрезок не пересекает последний отрезок из внутри полосы и при этом содержит её then добавить в конец else добавить в конец
Эта функция работает за
времени.Search In Strip
Зная
мы можем найти и используя следующую рекурсивную функцию:if then return Найдем
Здесь,
это функция объединения множеств и , упорядоченных по отношению . Время выполнения эквивалентно сумме времён каждого её запуска. Очевидно, что время работы -той функции, будет равно , где это соответствующие наборы .Учитывая лемму, заключаем, что функция работает за .
Предположим, что все отрезки лежат в полосе лемме , таким образом, число дополнительных отрезков, появляющихся после разрезаний пропорционально числу найденных пересечений.
. Таким образом в самом начале у нас есть пара . Что же дальше происходит: множество распадается в подмножества и , после чего лестница становится полностью соотносимой множеству . Необходимо найти пересечения отрезков из и , затем, все пересечения в . Чтобы найти пересечения отрезков в , мы режем полосу и множество по вертикале на полосы , и множества , соответственно, где c является медианой вершин отрезков, между и . Затем мы рекурсивно вызываем функцию к парам и . Ключевым является тот факт, что согласноОсновной алгоритм
Давайте разберемся с алгоритмом более подробно:
Не умаляя общности, предположим, что все пересечения и вершины отрезков имеют разные абсциссы (в конечном счете, их можно будет отсортировать введением дополнительных свойств). Будем рассматривать целые координаты на промежутке
. Пусть и будут координатами вершин -того отрезка.Основная задача нашего алгоритма, это рекурсивная функция
. Мы соединяем каждый вызов функции с узлом некоего двоичного дерева (далее рекурсивное дерево). Мы отмечаем все значения, множества и параметры вызова соответствующим узлом. В результате, мы проанализируем наш алгоритм рекурсивного дерева. Обозначим множество всех вершин рекурсивного дерева за , а множество внутренних вершин за .Отсортируем вершин по координатам и найдем ;
if then отсортируем по отношению ; ; return; Разделим на и так, что лестница будет полностью соотносима множеству ; Найдем ; ; Разделим отрезки из на пересекающих полосу и полосу ; ; ;
Отсюда и дальше
, и означают, соответственно, левого сына, правого сына, и отцовскую вершину узла . Наша задача показать, что все операции с узлом происходят за , и чтобы показать это, возьмем во внимание, что (очевидно, что ).Функция
похожа на функцию . Основная разница заключается в том, что вызывает себя без изменения полосы, когда делит полосу на две части, после чего рекурсивно вызывает себя для них. Другое отличие заключается в том, что множество не упорядочено так же, как . В результате мы не можем напрямую использовать функцию для эффективного деления .Чтобы решить эту проблему, представим
как объединение трех множеств: множества упорядоченного по отношению , неупорядоченного множества , и множества упорядоченного по отношению . Расположим отрезки из , пересекающие границу во множество , отрезки пересекающие во множество , и внутренние отрезки во множество (пример на рисунке справа).Примечания
Литература
Т.Вознюк, В.Терещенко — К построению эффективного решения задачи пересечения отрезков
Ф.Препарата, М.Шеймос — Вычислительная геометрия