
- •4. Задача поиска
- •4.1. Задача поиска на множестве
- •4.2. Задача динамического поиска
- •4.3. Порядковые статистики
- •4.4. Хеширование
- •4.5. Поиск подстрок
- •4.5.1. Алгоритм Рабина-Карпа
- •4.5.2. Алгоритм Кнута-Морриса-Пратта
- •4.5.3. Алгоритм Бойера-Мура
- •5. Сортировка, выпуклые оболочки
- •5.1. Задача сортировки
- •5.2. Задача построения выпуклой оболочки
- •5.2.1. Алгоритм Грэхема
- •5.2.2. Алгоритм Джарвиса
- •5.2.3. Метод разделяй и властвуй.
- •5.2.4. QuickHull
- •5.2.5. Алгоритм Чена
5.2.1. Алгоритм Грэхема
Грэхем предложил просматривать вершины
исходного множества в последовательности,
упорядоченной по величине угловой меры
множества векторов, построенных из
некоторой фиксированной точки к точкам
множества
.Как уже отмечалось, выпуклая оболочка
конечного множества
представляет собой выпуклый
многоугольник. Рассмотрим некоторую
внутреннюю точку
этого многоугольника (в предположении,
что он имеет непустую внутренность).
Для поиска такой точки можно зафиксировать
две вершины из
и, перебирая в качестве третьей оставшиеся
точки, найти треугольник, имеющий
непустую площадь. После этого необходимо
выбрать точку внутри этого треугольника.
Несложно видеть, что эта процедура в
худшем случае занимает
времени. Введем полярную систему
координат с центром в точке
.
Каждая точка множества
задается в полярных координатах парой
,
где
- угол наклона к оси абсцисс, а
- радиус. Линейный порядок на
определяется отношением:
,
если
или
при
.
Построенный порядок может быть получен
движением против часовой стрелки по
точкам из
луча с центром в точке
.
Этот процесс называется заметанием.
Поскольку для построения требуемого
линейного порядка можно использовать
любой алгоритм сортировки, то этот
процесс требует
времени. Следующий этап заключается в
сканировании слева направо построенной
последовательности с фильтрацией
вершин, которые не являются крайними.
Грэхем показал, что анализируя три
соседние точки
последовательности, можно ответить на
вопрос, является ли точка
внутренней точкой множества. Будем
говорить, что точки
образуют «правый поворот» (двигаясь по
прямолинейно от
к
через
,
в точке
мы поворачиваем направо), если внутренний
относительно точки
угол
больше или равен
.
В противном случае эти точки образуют
«левый поворот». Случай правого поворота
приведен на рисунке.
Из свойства выпуклости оболочки следует,
что при последовательном сканировании
ее точек делаются только левые повороты.
Из приведенного выше рисунка видно, что
точка
не является крайней, поскольку она
является внутренней точкой треугольника,
определяемого вершинами
.
Поскольку выпуклая оболочка представляет
выпуклый многоугольник с вершинами в
крайних точках, то при движении по ее
ребрам против часовой стрелки допустимы
только левые повороты. В силу вышесказанного
возможно два варианта продолжения
просмотра:
образуют правый поворот. Удалить вершину
,и проверить тройку
образуют левый поворот. Продолжить просмотр, перейдя к проверке тройки
Заметим, что формально направление поворота определяется знаком определителя векторного произведения
В качестве стартовой точки последовательности можно выбрать самую правую точку с наименьшей ординатой, которая заведомо включается в выпуклую оболочку.
Рассмотрим пример: Пусть точки на
плоскости отсортированы относительно
вершины
в порядке следования номеров:
На первом шаге рассматривается тройка вершин 1, 2, 3. В виду того, что мы имеем левый поворот, то на следующем шаге необходимо рассматривать вершины 2, 3, 4. Поскольку эта тройка образует правый поворот, то вершина 3 исключается из списка кандидатов на крайнюю вершину. Далее просмотр точек 1, 2, 4 исключает вершину 2. Последней в рассматриваемом фрагменте исключается вершина 5. В результате в конце просмотра данного фрагмента в списке остаются вершины 1, 4 и 6. Обход продолжается, пока не будет достигнута стартовая точка последовательности.
Таким образом, алгоритм построения
выпуклой оболочки по Грэхему состоит
в сортировке в определенном порядке
вершин исходного множества с дальнейшим
последовательным обходом этих вершин
и выборе крайних точек (или удалении
внутренних вершин). Проверка свойства
быть крайней точкой определяется
предикатом, который вычисляется на трех
соседних точках-кандидатах за константное
время. Поскольку каждое применение
предиката включает одну новую точку
последовательности, обход всех вершин
с построением выпуклой оболочки занимает
шагов. АТД для этой задачи, включает
операции удаления и позиционирования
текущих элементов со сдвигом влево и
вправо, в качестве структуры данных
естественно использовать двусторонние
циклические списки. Учитывая время,
необходимое для построения отсортированной
последовательности получим, что выпуклая
оболочка
точек на плоскости может быть найдена
за время
при памяти
с использованием только арифметических
операций и сравнений.
Эндрью было показано, что при сортировке можно не использовать полярные координаты, если множество точек разбить на два подмножества прямой, проходящей крайнюю левую и крайнюю правую точки. Тогда точки в каждом подмножестве сортируются по значению абсциссы, и алгоритм отдельно строит оболочку для каждого из множеств. В конце необходимо провести слияние полученных ломанных.
Следует отметить, что поскольку алгоритм
Грэхема требует предварительной
сортировки вершин исходного множества,
все точки этого множества должны быть
известны до начала работы алгоритма.
Если требуется модификация строящейся
оболочки при поступлении новых вершин
в реальном времени (on-line
режим), то самый простой способ -
перезапустить алгоритм на новых данных.
Но при этом, если добавляютсявершин, сложность алгоритма составляет
.
Если после получения каждой новой
вершины не производить сортировку
заново, а вставлять полученную вершину
в отсортированную последовательность,
то сложность алгоритма можно понизить
до
.
Препарата показал, что используя
сбалансированные деревья поиска для
хранения и поиска вершин можно построить
открытый алгоритм сложности
.
Интересные структуры данных возникают,
когда в реальном времени разрешается
как добавление новых вершин, так и
удаление существующих[5].