Алгоритмы построения выпуклых оболочек множества точек на плоскости — различия между версиями
(→Алгоритм Джарвиса) |
(→Алгоритм Грэма) |
||
Строка 53: | Строка 53: | ||
==Алгоритм Грэма== | ==Алгоритм Грэма== | ||
+ | |||
+ | ===Псевдокод=== | ||
+ | |||
+ | v = begin; | ||
+ | w = prev(v); | ||
+ | f = false; | ||
+ | |||
+ | while (next(v) != begin || f == false) | ||
+ | { | ||
+ | if (next(v) == w) | ||
+ | f:= true; | ||
+ | if (left_turn(v, next(v), next(next(v)))) | ||
+ | v = next(v); | ||
+ | else | ||
+ | { | ||
+ | next(v).erase(); | ||
+ | v = prev(v); | ||
+ | } | ||
+ | } | ||
==Алгоритм Эндрюса== | ==Алгоритм Эндрюса== |
Версия 17:27, 2 мая 2012
Содержание
Выпуклая оболочка множества точек
Определение: |
Выпуклой оболочкой множества точек называется пересечение всех выпуклых множеств, содержащих все заданные точки. |
Еще одно определение:
Определение: |
Выпуклой оболочкой множества точек называется линейная комбинация минимального набора точек, дающая все остальные точки. |
Будем рассматривать множество точек на плоскости и способы построения их выпуклых оболочек.
Некоторые свойства выпуклых оболочек:
- Экстремальные всегда принадлежат выпуклой оболочке.
- Для равномерно распределенных в прямоугольнике точек, выпуклая оболочка будет состоять из логарифма точек.
- Если в изначальном массиве точка на 0-й позиции будет самой левой, то после построения выпуклой оболочки in-place она останется там же.
Алгоритм Джарвиса
Алгоритм Джарвиса определяет последовательность точек, образующую выпуклую оболочку множества точек на плоскости. Так же известен как алгоритм "заворачивания подарка".
Время работы алгоритма —
, где — количество точек в выпуклой оболочке. В случае получаем .Алгоритм в силу своей простоты легко реализуется in-place.
Описание Алгоритма
Рассмотрим конечное множество точек
Cамая левая нижняя точка
лежит на выпуклой оболочке. Точка — точка с наименьшим полярным угломПсевдокод
int jarvis(std::vector<dot> &dots) { int last = 0; dots.push_back(dots[0]); int size = dots.size(); do { for(int i = last + 2; i < size; i++) { std::swap(dots[last + 1], max_element(dots[last + 1], dots[i])); } } while(dots[last] != dots[0]); std::swap(dots[last], dots[size - 1]); dots.pop_back(); return last; };
Алгоритм Грэма
Псевдокод
v = begin; w = prev(v); f = false; while (next(v) != begin || f == false) { if (next(v) == w) f:= true; if (left_turn(v, next(v), next(next(v)))) v = next(v); else { next(v).erase(); v = prev(v); } }
Алгоритм Эндрюса
Алгоритм Merge hull
Алгоритм Quick hull
Алгоритм Чена
Алгоритм Чена строит выпуклую оболочку конечного множества точек за
без вырожденных случаев, где — количество точек в выпуклой оболочке. Основная идея заключается в том, чтобы разделить изначальное множество точек на группы по элементов, построить выпуклые оболочки для каждой из групп, потом слить их в одну общую оболочку.Алгоритм состоит из трех этапов
- Разбиение исходного множества точек на группы по элементов в каждой.
- Построение выпуклых оболочек для групп.
- Объединение выпуклых оболочек.
Предположим, что
нам известно.Исходное множество точек можно разбивать на группы любым способом. Для простоты будем выделять группы просто по порядку. Первые
элементов — первая группа, следующие элементов — вторая группа и так далее.Строить выпуклые оболочки для групп можно с помощью алгоритма Грэма за
. Всего групп, получаем суммарную асимптотикуДля объединения оболочек будем использовать обход по Джарвису. Самая левая точка точно лежит на общей внутренней оболочке. Научимся находить следующую точку. предположим, что мы умеем находить опорную прямую за
Всего оболочек . Получается, что точку мы умеем находить за Всего точек на выпуклой оболочке . Получаем объеденение оболочек за .Выбор числа h
Заметим, что нам не обязательно знать точное значение
. Нас утроит любое значение , такое что .Будем использовать следующий метод:
Будем брать
, пока . На каждую итерацию потребуется ..
Посчитаем, сколько нам понадобится времени на поиск