Алгоритмы построения выпуклых оболочек множества точек на плоскости
Содержание
Выпуклая оболочка множества точек
Определение: |
Выпуклой оболочкой множества точек называется пересечение всех выпуклых множеств, содержащих все заданные точки. |
Еще одно определение:
Определение: |
Выпуклой оболочкой множества точек называется линейная комбинация минимального набора точек, дающая все остальные точки. |
Некоторые свойства выпуклых оболочек:
- Экстремальные всегда принадлежат выпуклой оболочке.
- Для равномерно распределенных в прямоугольнике точек, выпуклая оболочка будет состоять из логарифма точек.
- Если в изначальном массиве точка на 0-й позиции будет самой левой, то после построения выпуклой оболочки in-place она останется там же.
Пусть нам дано конечное множество точек на плоскости
— cамая левая нижняя точка, лежит на выпуклой оболочке.Рассмотрим алгоритмы, позволяющие построить выпуклую оболочку
Алгоритм Джарвиса
Алгоритм Джарвиса определяет последовательность точек, образующую выпуклую оболочку множества точек на плоскости. Так же известен как алгоритм "заворачивания подарка".
Время работы алгоритма —
, где — количество точек в выпуклой оболочке. В случае получаем .Алгоритм в силу своей простоты легко реализуется in-place.
Описание Алгоритма
Будем находить точку, с наименьшим полярным углом от предыдущей стороны. Если таких точек несколько - брать самую дальнюю. И так до тех пор, пока выпуклая оболочка не замкнется.
Псевдокод
dot max_element(int j, int i) { if (left_turn(dots[j - 1], dots[j], dots[i])) return dots[j]; else return dots[i]; } 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(last + 1, 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
Заметим, что нам не обязательно знать точное значение
. Нас утроит любое значение , такое что .Будем использовать следующий метод:
Будем брать
, пока . На каждую итерацию потребуется ..
Посчитаем, сколько нам понадобится времени на поиск