Алгоритм Форчуна

Материал из testwiki
Перейти к навигации Перейти к поиску
Анимация алгоритма Форчуна

Алгоритм Форчуна — это алгоритм заметающей прямой для генерации диаграммы Вороного из набора точек на плоскости за время O(nlogn) с использованием памяти O(n)Шаблон:SfnШаблон:Sfn. Алгоритм первоначально опубликовал Стивен Форчун в 1986 в своей статье «Алгоритм заметающей прямой для диаграмм Вороного»Шаблон:Sfn.

Описание алгоритма

Алгоритм поддерживает заметающую прямую и береговую линию, которые двигаются по плоскости в процессе работы алгоритма. Заметающая прямая — это прямая, которую мы по традиции можем считать вертикальной и движущейся слева направо. В любой момент работы алгоритма точки из набора слева от заметающей прямой будут включены в диаграмму Вороного, в то время как точки справа от заметающей прямой ещё не отработаны. Береговая линия не является прямой, а является сложной, состоящей из кусочков парабол, кусочно-заданной кривой слева от заметающей прямой. Она отделяет порцию плоскости, внутри которой диаграмма Вороного может быть известна, независимо от других точек справа от заметающей прямой. Для каждой точки слева от заметающей прямой можно определить параболу для точки, которая равноудалена как от этой точки, так и от заметающей прямой. Береговая линия — это граница объединений этих парабол. По мере движения прямой вершины береговой линии, в которых две параболы пересекаются, вычерчивают рёбра диаграммы Вороного. Береговая линия продвигается, сохраняя основание каждой параболы в точности на половину пути между начальным положением заметающей прямой и новой позицией заметающей прямой. Математически это значит, что каждая парабола образуется с помощью заметающей прямой как директрисы, а заданная точка из набора служит фокусом.

Алгоритм поддерживает структуру данных двоичного дерева, описывающего комбинаторную структуру береговой линии, и очередь с приоритетом, перечисляющую потенциальные события в будущем, которые могли бы изменить структуру береговой линии. Эти события включают добавление другой параболы в береговую линию (когда заметающая прямая проходит через другую входную точку) и удаление кривой из береговой линии (когда заметающая прямая становится касательной к окружности через некоторые три входных точки, параболы которых образуют последовательные сегменты береговой линии). Каждому такому событию может быть присвоен приоритет по x-координате заметающей прямой в точке, где событие произошло. Алгоритм состоит из последовательного удаления события из очереди с приоритетом, нахождения изменений событий в береговой линии и обновление структуры данных.

Так как имеется O(n) событий для обработки (каждое ассоциировано с некоторым свойством диаграммы Вороного) и времени O(log n) для обработки события (которое состоит из постоянного числа поисков по двоичному дереву и операций очереди с приоритетом), общее время равно O(nlogn).

Псевдокод

Псевдокод алгоритмаШаблон:Sfn.

Пусть *(z) будет преобразованием *(z)=(zx,zy+d(z)),
  где d(z) — евклидово расстояние между  Шаблон:Mvar и ближайшей точкой
Пусть Шаблон:Mvar будет «береговой линией»
Пусть Rp будет областью, покрывающей точку Шаблон:Mvar.
Пусть Cpq будет граничным лучом между точками Шаблон:Mvar и Шаблон:Mvar.
Пусть p1,p2,...,pm будут точками с минимальной Шаблон:Mvar-координатой, упорядоченными по Шаблон:Mvar-координате
QSp1,p2,...,pm
создаёт начальные вертикальные граничные лучи Cp1,p20,Cp2,p30,...Cpm1,pm0
T*(Rp1),Cp1,p20,*(Rp2),Cp2,p30,...,*(Rpm1),Cpm1,pm0,*(Rpm)
пока не IsEmpty(Шаблон:Mvar) выполнить
    pDeleteMin(Q)
    в случае если 
    Шаблон:Mvar является точкой в *(V):
        Находим область *(Rq) в Шаблон:Mvar, содержащую Шаблон:Mvar,
          ограниченную кривой Crq слева и кривой Cqs справа
        создаём новые граничные лучи Cpq и Cpq+ с основанием Шаблон:Mvar
        заменяем *(Rq) на *(Rq),Cpq,*(Rp),Cpq+,*(Rq) в Шаблон:Mvar
        удаляем из Шаблон:Mvar любое пересечение между Crq и Cqs
        вставляем в Шаблон:Mvar любое пересечение Crq и Cpq
        вставляем в Шаблон:Mvar любое пересечение Cpq+ и Cqs
    Шаблон:Mvar является вершиной Вороного в *(V):
        пусть Шаблон:Mvar будет пересечением Cqr слева и Crs справа
        пусть Cuq будет левым соседом Cqr и
          пусть Csv будет правым соседом Crs в Шаблон:Mvar
        создаём новый граничный луч Cqs0, если qy=sy,
          или создаём Cqs+, если Шаблон:Mvar правая часть более высокой  из Шаблон:Mvar и Шаблон:Mvar,
          в противном случае создаём Cqs
        заменяем Cqr,*(Rr),Crs на вновь созданную Cqs в Шаблон:Mvar
        удаляем из Шаблон:Mvar любое пересечение Cuq и Cqr
        удаляем из Шаблон:Mvar любое пересечение Crs и Csv
        вставляем в Шаблон:Mvar любое пересечение Cuq и Cqs
        вставляем в Шаблон:Mvar любое пересечение Cqs и Csv
        записываем Шаблон:Mvar как вершину Cqr и Crs и основание Cqs
        выводим сегменты границ Cqr и Crs
    конец в случае
конец пока
выводим оставшиеся граничные лучи из Шаблон:Mvar

Взвешенные стороны и диски

Как указывает ФорчунШаблон:Sfn, модифицированная версия алгоритма заметающей прямой может быть использована для построения аддитивно взвешенной диаграммы Вороного, в которой расстояние до каждой точки нейтрализуется весом точки. Это можно рассматривать эквивалентно как диаграмма Вороного набора дисков с центрами в точках и радиусом, равным весу точки.

Взвешенные точки можно использовать для контроля площадей ячеек Вороного, когда диаграммы Вороного используются для построения Шаблон:Не переведено 5. В аддитивно взвешенной диаграмме Вороного биссектрисой между точками в общем случае является гипербола, в противоположность невзвешенным диаграммам Вороного и Шаблон:Не переведено 5 дисков, для которых это прямая.

Примечания

Шаблон:Примечания

Литература

Шаблон:Refbegin

Шаблон:Refend

Ссылки

Шаблон:Rq