Алгоритм Балабана — различия между версиями
(→Search In Strip) |
(→Перевод) |
||
| Строка 116: | Строка 116: | ||
Что же дальше происходит: множество <tex>S</tex> ''распадается'' в подмножества <tex>Q</tex> и <tex>S'</tex>, после чего лестница <tex>D = (Q, \langle a, b \rangle)</tex> становится полностью соотносимой множеству <tex>S'</tex>. Необходимо найти пересечения отрезков из <tex>D</tex> и <tex>S'</tex>, затем, все пересечения в <tex>S'</tex>. Чтобы найти пересечения отрезков в <tex>S'</tex>, мы ''режем'' полосу <tex>\langle a, b \rangle</tex> и множество <tex>S'</tex> по вертикале <tex>x = c</tex> на полосы <tex>\langle a, c \rangle</tex>, <tex>\langle c, b \rangle</tex> и множества <tex>S'_{ls}</tex>, <tex>S'_{rs}</tex> соответственно, где c является медианой вершин отрезков, между <tex>a</tex> и <tex>b</tex>. Затем мы рекурсивно вызываем функцию к парам <tex>(S'_{ls}, \langle a, c \rangle)</tex> и <tex>(S'_{rs}, \langle c, b \rangle)</tex>. Ключевым является тот факт, что согласно [[#lemma1|лемме]] <tex>|S'| \le Ends_{a, b}(S') + |Int(D, S')|</tex>, таким образом, число дополнительных отрезков, появляющихся после ''разрезаний'' пропорционально числу найденных пересечений. | Что же дальше происходит: множество <tex>S</tex> ''распадается'' в подмножества <tex>Q</tex> и <tex>S'</tex>, после чего лестница <tex>D = (Q, \langle a, b \rangle)</tex> становится полностью соотносимой множеству <tex>S'</tex>. Необходимо найти пересечения отрезков из <tex>D</tex> и <tex>S'</tex>, затем, все пересечения в <tex>S'</tex>. Чтобы найти пересечения отрезков в <tex>S'</tex>, мы ''режем'' полосу <tex>\langle a, b \rangle</tex> и множество <tex>S'</tex> по вертикале <tex>x = c</tex> на полосы <tex>\langle a, c \rangle</tex>, <tex>\langle c, b \rangle</tex> и множества <tex>S'_{ls}</tex>, <tex>S'_{rs}</tex> соответственно, где c является медианой вершин отрезков, между <tex>a</tex> и <tex>b</tex>. Затем мы рекурсивно вызываем функцию к парам <tex>(S'_{ls}, \langle a, c \rangle)</tex> и <tex>(S'_{rs}, \langle c, b \rangle)</tex>. Ключевым является тот факт, что согласно [[#lemma1|лемме]] <tex>|S'| \le Ends_{a, b}(S') + |Int(D, S')|</tex>, таким образом, число дополнительных отрезков, появляющихся после ''разрезаний'' пропорционально числу найденных пересечений. | ||
| − | === | + | ===Основной алгоритм=== |
Давайте разберемся с алгоритмом более подробно: | Давайте разберемся с алгоритмом более подробно: | ||
| − | Не умаляя общности, предположим, что все пересечения и вершины отрезков имеют разные абсциссы (в конечном счете, их можно будет отсортировать введением дополнительных свойств). Будем рассматривать целые координаты на промежутке <tex> | + | Не умаляя общности, предположим, что все пересечения и вершины отрезков имеют разные абсциссы (в конечном счете, их можно будет отсортировать введением дополнительных свойств). Будем рассматривать целые координаты на промежутке <tex>[1, 2N]</tex>. Пусть <tex>p_i</tex> и <tex>s(i)</tex> будут координатами вершин <tex>i</tex>-того отрезка.(???) |
Основная задача нашего алгоритма, это рекурсивная функция <tex>TreeSearch</tex>. Мы соединяем каждый вызов функции с узлом некоего двоичного дерева (далее ''рекурсивное дерево''). Мы отмечаем все значения, множества и параметры вызова соответствующим узлом. В результате, мы проанализируем наш алгоритм рекурсивного дерева. Обозначим множество всех вершин рекурсивного дерева за <tex>RT</tex>, а множество внутренних вершин за <tex>V</tex>. (WAT??) | Основная задача нашего алгоритма, это рекурсивная функция <tex>TreeSearch</tex>. Мы соединяем каждый вызов функции с узлом некоего двоичного дерева (далее ''рекурсивное дерево''). Мы отмечаем все значения, множества и параметры вызова соответствующим узлом. В результате, мы проанализируем наш алгоритм рекурсивного дерева. Обозначим множество всех вершин рекурсивного дерева за <tex>RT</tex>, а множество внутренних вершин за <tex>V</tex>. (WAT??) | ||
<tex>IntersectingPairs(S_v, a, b):</tex> | <tex>IntersectingPairs(S_v, a, b):</tex> | ||
| − | + | Отсортируем <tex>2 \cdot N</tex> вершин по координатам и | |
| − | + | найдем <tex>p_i, s(i), i = 1,...,2 \cdot N;\ S_r \leftarrow S_0</tex> | |
| − | <tex>TreeSearch(S_r, 1, 2 | + | <tex>TreeSearch(S_r, 1, 2 \cdot N)</tex>; |
<tex>TreeSearch(S_r, a, b):</tex> | <tex>TreeSearch(S_r, a, b):</tex> | ||
| + | <tex>\{</tex> | ||
'''if''' <tex>b - a = 1</tex> '''then''' | '''if''' <tex>b - a = 1</tex> '''then''' | ||
<tex>\{</tex> | <tex>\{</tex> | ||
| − | <tex>L \leftarrow | + | <tex>L \leftarrow</tex> отсортируем <tex>S_v</tex> по отношению <tex><_b</tex>; |
<tex>SearchInStrip_{a, b}(L_v, R_v)</tex>; | <tex>SearchInStrip_{a, b}(L_v, R_v)</tex>; | ||
| − | + | return; | |
<tex>\}</tex> | <tex>\}</tex> | ||
| − | + | Разделим <tex>S_v</tex> на <tex>Q_v</tex> и <tex>S_v'</tex> так, что лестница | |
| − | + | <tex>D_v := (Q_v, \langle a, b \rangle)</tex> будет полностью соотносима множеству <tex>S_v'</tex>; | |
| − | + | Найдем <tex>Int(D_v, S_v')</tex>; | |
| − | c:= | + | <tex>c := \lfloor (a + b)/2 \rfloor</tex>; |
| − | + | Разделим отрезки из <tex>S_v'</tex> на пересекающих | |
| − | + | полосу <tex>\langle a, c \rangle</tex> <tex>S_{ls}(v)</tex> и | |
| − | + | полосу <tex>\langle c, b \rangle</tex> <tex>S_{rs}(v)</tex>; | |
| − | TreeSearch( | + | <tex>TreeSearch(S_{ls}(v), a, c)</tex>; |
| − | TreeSearch( | + | <tex>TreeSearch(S_{rs}(v), c, b)</tex>; |
| − | + | <tex>\}</tex> | |
| + | |||
| + | Отсюда и дальше <tex>ls(v)</tex>, <tex>rs(v)</tex> и <tex>ft(v)</tex> означают, соответственно, левого сына, правого сына, и отцовскую вершину узла <tex>v<.tex>. | ||
==Примечания== | ==Примечания== | ||
Версия 15:24, 13 ноября 2013
Алгоритм Балабана — детерминированный алгоритм, позволяющий по множеству отрезков на плоскости получить множество точек, в которых эти отрезки пересекаются.
Содержание
Введение
Решение задачи по поиску множества пересечений отрезков является одной из главных задач вычислительной геометрии. Тривиальный детерминированный алгоритм имеет временную сложность , и его суть заключается в проверке попарного пересечения отрезков. Сложнее, но эффективнее алгоритм Бентли-Оттмана [1] с оценкой сложности , в основе которого лежит метод заметающей прямой. Алгоритм, предложенный Чазелле и Едельсбруннером [2], имеет лучшую оценку , но в отличие от предыдущих методов требует квадратичной памяти. Оптимальный детерминированный алгоритм был предложен Балабаном [3] с временной оценкой сложности и памяти, где К - число пересекающихся отрезков. При количестве отрезков равным 2000 и большому количеству пересечений целесообразно использовать алгоритм Балабана. Однако в результате громоздкости и высокой сложности реализации алгоритма в большинстве практических задач используется алгоритм заметающей прямой Бентли-Оттмана.
Основные понятия
Введем некоторые обозначения. Пусть - множество всех точек пересечения отрезков из множества , а - количество таких пересечений ;
Через обозначим вертикальную полосу, которая ограничена прямыми и , а через — отрезок с вершинами в точках с абсциссами и .
Рассмотрим взаимное расположение вертикальной полосы и отрезка .
| Определение: |
| Будем говорить, что отрезок , с вершинами в точках с абсциссами и :
- содержит(span) полосу , если ; |
| Определение: |
| Два отрезка и называются пересекающимися внутри полосы , если их точка пересечения лежит в пределах этой полосы. Для двух множеств отрезков и определим множество как . |
Обозначения и будут использоваться для описания подмножеств и , состоящих из пересекающихся пар отрезков в пределах полосы . Далее скобки используются для определения неупорядоченных наборов, а скобки используются для определения упорядоченных множеств.
Введем отношение порядка на множестве отрезков если оба отрезка пересекают вертикальную линию и точка пересечения этой прямой с отрезком лежит ниже точки пересечения с .
− любой отрезок из содержит полосу ;
− нет пересечений отрезков внутри лестницы;
− упорядочена по отношению .
| Определение: |
| Будем называть лестницу полностью соотносимой множеству отрезков , если каждый отрезок из либо не пересекает полосу , либо пересекает хотя бы одну из ступенек из множества . |
| Лемма: |
Если лестница полностью соотносима множеству отрезков , где состоит из отрезков, пересекающих полосу , тогда , где это число вершин отрезков , находящихся в пределах полосы . |
| Определение: |
| Если точка отрезка лежит между ступеньками и , тогда число называется местоположением на лестнице и обозначается как |
| Утверждение: |
Имея лестницу и множество отрезков , множество можно найти за время . Однако, если упорядочено отношением , где , тогда можно найти за время . |
Алгоритм
Введем несколько дополнительных функций, чтобы упростить основной алгоритм:
Split
Функция разделяет входное множество отрезков , пересекающих некоторую полосу , на подмножества и так, что лестница полностью соотносима множеству отрезков .
Пусть , где for do if отрезок не пересекает последний отрезок из внутри полосы и при этом содержит её then добавить в конец else добавить в конец
Эта функция работает за времени.
Search In Strip
Зная мы можем найти и используя следующую рекурсивную функцию:
if then return Найдем
Здесь, это функция объединения множеств и , упорядоченных по отношению . Время выполнения эквивалентно сумме времён каждого её запуска. Очевидно, что время работы -той функции, будет равно , где это соответствующие наборы .
Учитывая лемму, заключаем, что функция работает за .
Предположим, что все отрезки лежат в полосе . Таким образом в самом начале у нас есть пара . Что же дальше происходит: множество распадается в подмножества и , после чего лестница становится полностью соотносимой множеству . Необходимо найти пересечения отрезков из и , затем, все пересечения в . Чтобы найти пересечения отрезков в , мы режем полосу и множество по вертикале на полосы , и множества , соответственно, где c является медианой вершин отрезков, между и . Затем мы рекурсивно вызываем функцию к парам и . Ключевым является тот факт, что согласно лемме , таким образом, число дополнительных отрезков, появляющихся после разрезаний пропорционально числу найденных пересечений.
Основной алгоритм
Давайте разберемся с алгоритмом более подробно:
Не умаляя общности, предположим, что все пересечения и вершины отрезков имеют разные абсциссы (в конечном счете, их можно будет отсортировать введением дополнительных свойств). Будем рассматривать целые координаты на промежутке . Пусть и будут координатами вершин -того отрезка.(???)
Основная задача нашего алгоритма, это рекурсивная функция . Мы соединяем каждый вызов функции с узлом некоего двоичного дерева (далее рекурсивное дерево). Мы отмечаем все значения, множества и параметры вызова соответствующим узлом. В результате, мы проанализируем наш алгоритм рекурсивного дерева. Обозначим множество всех вершин рекурсивного дерева за , а множество внутренних вершин за . (WAT??)
Отсортируем вершин по координатам и найдем ;
if then отсортируем по отношению ; ; return; Разделим на и так, что лестница будет полностью соотносима множеству ; Найдем ; ; Разделим отрезки из на пересекающих полосу и полосу ; ; ;
Отсюда и дальше , и означают, соответственно, левого сына, правого сына, и отцовскую вершину узла <tex>v<.tex>.
Примечания
Литература
Т.Вознюк, В.Терещенко — К построению эффективного решения задачи пересечения отрезков
Ф.Препарата, М.Шеймос — Вычислительная геометрия