Статические выпуклые оболочки: Джарвис, Грэхем, Эндрю, Чен, QuickHull — различия между версиями
Yurik (обсуждение | вклад) (→Псевдокод) |
Yurik (обсуждение | вклад) (→Алгоритм QuickHull) |
||
Строка 121: | Строка 121: | ||
= Алгоритм Чена = | = Алгоритм Чена = | ||
= Алгоритм QuickHull = | = Алгоритм QuickHull = | ||
+ | |||
+ | == Описание Алгоритма == | ||
+ | [[File:hull.png|thumb|250px|Промежуточный шаг алгоритма. Для прямой <tex>p_i p_1</tex> нашли точку <tex>p</tex>. Над прямыми <tex>p_i p</tex> и <tex>p p_1</tex> точек нет, поэтому переходим к следующей прямой <tex>p_0 p_i</tex>.]] | ||
+ | |||
+ | 1)Найдем самую левую нижнюю точку <tex>p_0</tex> и самую правую нижнюю точку <tex>p_1</tex>. | ||
+ | |||
+ | 2)Возьмем все точки выше прямой <tex>p_0 p_1</tex>. | ||
+ | |||
+ | 3)Найдем среди этого множества точку <tex>p_i</tex>, наиболее отдаленную от прямой (если таких несколько, взять самую правую). | ||
+ | |||
+ | 4)Рекурсивно повторить шаги 2-3 для прямых <tex>p_0 p_i</tex> и <tex>p_i p_1</tex>, пока есть точки. | ||
+ | |||
+ | 5)Добавить в ответ точки <tex>p_0 .. p_i .. p_1</tex>, полученные в п. 3. | ||
+ | |||
+ | 6)Повторить пункты 2-5 для <tex>p_1 p_0</tex> (то есть для "нижней" половины). | ||
+ | |||
+ | 7)Ответ - объединение списков из п. 5 для верхней и нижней половины. | ||
+ | |||
+ | <br/><br/> | ||
+ | |||
+ | == Корректность == | ||
+ | |||
+ | [[File:hull1.png|thumb|200px|]] | ||
+ | |||
+ | Очевидно, что выпуклая оболочка всего множества является объединением выпуклых оболочек для верхнего и нижнего множества. Докажем, что алгоритм верно строит оболочку для верхнего множества, для правого рассуждения аналогичны. | ||
+ | Точки <tex>p_0</tex> и <tex>p_1</tex> принадлежат оболочке. | ||
+ | |||
+ | * Пусть какая-то точка входит в нашу оболочку, но не должна. | ||
+ | |||
+ | Назовем эту точку <tex>t</tex>. По алгоритму эта точка появилась как самая удаленная от некой прямой <tex>t_1 t_2</tex>. Так как <tex>t</tex> не входит в оболочку, то существует прямая <tex>t_3 t_4</tex> из настоящей выпуклой оболочки, что <tex>t</tex> лежит снизу от прямой. Тогда какая-то из <tex>t_3</tex> и <tex>t_4</tex> удалена от прямой дальше <tex>t</tex>, что противоречит алгоритму. | ||
+ | |||
+ | * Наоборот, пусть какой-то точки <tex>t</tex> в нашей оболочке нет, а должна быть. | ||
+ | |||
+ | Пойдем вниз рекурсии в те ветки, где есть <tex>t</tex>. В какой-то момент <tex>t</tex> окажется внутри некоторого треугольника. Но тогда возникает противоречие с тем, что <tex>t</tex> принадлежит выпуклой оболочке - противоречие. | ||
+ | |||
+ | Таким образом, наша оболочка совпадает с истинной, а значит алгоритм корректен. | ||
+ | |||
+ | == Псевдокод == | ||
+ | |||
+ | |||
+ | |||
+ | == Сложность == | ||
+ | |||
+ | Пусть время, необходимое для нахождения оболочки над некой прямой и множеством точек <tex>S</tex> есть <tex>T(S)</tex> | ||
+ | Тогда <tex>T(S) = O(\|S\|) + T(A \in S) + T(B \in S)</tex>, где <tex>A, B</tex> - множества над полученными прямыми. Отсюда видно, что в худшем случае, алгоритм тратит <tex>O(n^2)</tex>. На рандомных же данных это число равно <tex>O(n \log n)</tex> | ||
+ | |||
+ | == Ссылки == | ||
+ | |||
+ | * [http://en.wikipedia.org/wiki/QuickHull Английская статья — Wikipedia] |
Версия 16:06, 16 января 2014
Конспект не готов. |
Ниже приводятся основные алгоритмы построения выпуклых оболочек статического множества. Используются обозначения:
- размер входных данных, - размер оболочки.Алгоритм Джарвиса
По-другому "Gift wrapping algorithm" (Заворачивание подарка).
Описание Алгоритма
1) Возьмем самую правую нижнюю точку
нашего множества. Добавляем ее в ответ.2) На каждом следующем шаге для последнего добавленного
ищем среди всех недобавленных точек и с максимальным полярным углом относительно (Если углы равны, надо сравнивать по расстоянию). Добавляем в ответ. Если , заканчиваем алгоритм.
Корректность
Точка
, очевидно, принадлежит оболочке. На каждом последующем шаге алгоритма мы получаем прямую , по построению которой все точки множества лежат слева от нее. Значит, выпуклая оболочка состоит из -ых и только из них.Псевдокод
Inplace-реализация алгоритма.
- исходное множество,Jarvis(S) find i such that S[i] has the lowest y-coordinate and highest x-coordinate p0 = S[i] pi = p0 k = 0 do k++ for i = k..n if S[i] has lower angle and higher distance than S[k] in relation to pi swap(S[i], S[k]) pi = S[k] while pi != p0 return k
Сложность
Добавление каждой точки в ответ занимает
времени, всего точек будет , поэтому итоговая сложность .Ссылки
Алгоритм Грэхема
Описание Алгоритма
1)Находим самую правую нижнюю точку множества
, добавляем в ответ.2)Сортируем все остальные точки по полярному углу относительно
.3)Добавляем в ответ
- самую первую из отсортированных точек.4)Берем следующую по счету точку
. Пока и две последних точки в текущей оболочке и образуют неправый поворот, удаляем из оболочки .5)Добавляем в оболочку
.6)Делаем п.5, пока не закончатся точки.
Корректность
Конспект не готов. |
Докажем, что на каждом шаге множество
-тых является выпуклой оболочкой всех уже рассмотренных точек. Доказательство проведем по индукции.1)База. Для трех первых точек утверждение, очевидно, выполняется.
2)Переход. Предположим от противного, что утверждение на
-м шаге перестает выполняться. Тогда существует два варианта:- В нашей оболочке есть лишние точки.
Этого не может быть, так как на каждом шаге мы добавляем ровно одну точку, которая точно входит в оболочку, так как имеет наибольший полярный угол среди всех остальных.
- В нашей оболочке нет каких-то точек, которые есть в настоящей.
Удаляем мы только те
Псевдокод
Inplace-реализация алгоритма.
- исходное множество,Graham(S) find i such that S[i] has the lowest y-coordinate and highest x-coordinate swap(S[i], S[1]) sort S[2..n] by angle in relation to S[1] k = 2 for p = 3..n while S[k - 1], S[k], S[p] has non-right orientation k-- swap(S[p], S[k + 1]) return k
Сложность
Сортировка точек занимает
времени. При обходе каждая точка добавляется в ответ не более одного раза, поэтому сложность этой части - . Суммарное время - .Ссылки
Алгоритм
Описание Алгоритма
Корректность
Псевдокод
Сложность
Ссылки
Алгоритм Чена
Алгоритм QuickHull
Описание Алгоритма
1)Найдем самую левую нижнюю точку
и самую правую нижнюю точку .2)Возьмем все точки выше прямой
.3)Найдем среди этого множества точку
, наиболее отдаленную от прямой (если таких несколько, взять самую правую).4)Рекурсивно повторить шаги 2-3 для прямых
и , пока есть точки.5)Добавить в ответ точки
, полученные в п. 3.6)Повторить пункты 2-5 для
(то есть для "нижней" половины).7)Ответ - объединение списков из п. 5 для верхней и нижней половины.
Корректность
Очевидно, что выпуклая оболочка всего множества является объединением выпуклых оболочек для верхнего и нижнего множества. Докажем, что алгоритм верно строит оболочку для верхнего множества, для правого рассуждения аналогичны. Точки
и принадлежат оболочке.- Пусть какая-то точка входит в нашу оболочку, но не должна.
Назовем эту точку
. По алгоритму эта точка появилась как самая удаленная от некой прямой . Так как не входит в оболочку, то существует прямая из настоящей выпуклой оболочки, что лежит снизу от прямой. Тогда какая-то из и удалена от прямой дальше , что противоречит алгоритму.- Наоборот, пусть какой-то точки в нашей оболочке нет, а должна быть.
Пойдем вниз рекурсии в те ветки, где есть
. В какой-то момент окажется внутри некоторого треугольника. Но тогда возникает противоречие с тем, что принадлежит выпуклой оболочке - противоречие.Таким образом, наша оболочка совпадает с истинной, а значит алгоритм корректен.
Псевдокод
Сложность
Пусть время, необходимое для нахождения оболочки над некой прямой и множеством точек
есть Тогда , где - множества над полученными прямыми. Отсюда видно, что в худшем случае, алгоритм тратит . На рандомных же данных это число равно