Построение алгоритма.

Самые лучшие и честные брокеры бинарных опционов в 2020 году:
  • Бинариум
    Бинариум

    1 место! Лидер на рынке — самый честный брокер бинарных опционов!
    Идеально для новичков — предоставляется бесплатное онлайн-обучение и демо-счет!
    Получите бонус за регистрацию по ссылке:

Блок-схемы алгоритмов. ГОСТ. Примеры

Схемаэто абстракция какого-либо процесса или системы, наглядно отображающая наиболее значимые части. Схемы широко применяются с древних времен до настоящего времени — чертежи древних пирамид, карты земель, принципиальные электрические схемы. Очевидно, древние мореплаватели хотели обмениваться картами и поэтому выработали единую систему обозначений и правил их выполнения. Аналогичные соглашения выработаны для изображения схем-алгоритмов и закреплены ГОСТ и международными стандартами.

На территории Российской Федерации действует единая система программной документации (ЕСПД), частью которой является Государственный стандарт — ГОСТ 19.701-90 «Схемы алгоритмов программ, данных и систем» [1]. Не смотря на то, что описанные в стандарте обозначения могут использоваться для изображения схем ресурсов системы, схем взаимодействия программ и т.п., в настоящей статье описана лишь разработка схем алгоритмов программ.

Рассматриваемый ГОСТ практически полностью соответствует международному стандарту ISO 5807:1985.

Содержание:

Элементы блок-схем алгоритмов

Блок-схема представляет собой совокупность символов, соответствующих этапам работы алгоритма и соединяющих их линий. Пунктирная линия используется для соединения символа с комментарием. Сплошная линия отражает зависимости по управлению между символами и может снабжаться стрелкой. Стрелку можно не указывать при направлении дуги слева направо и сверху вниз. Согласно п. 4.2.4, линии должны подходить к символу слева, либо сверху, а исходить снизу, либо справа.

Есть и другие типы линий, используемые, например, для изображения блок-схем параллельных алгоритмов, но в текущей статье они, как и ряд специфических символов, не рассматриваются. Рассмотрены лишь основные символы, которых всегда достаточно студентам.

Терминатор начала и конца работы функции Терминатором начинается и заканчивается любая функция. Тип возвращаемого значения и аргументов функции обычно указывается в комментариях к блоку терминатора.

Операции ввода и вывода данных В ГОСТ определено множество символов ввода/вывода, например вывод на магнитные ленты, дисплеи и т.п. Если источник данных не принципиален, обычно используется символ параллелограмма. Подробности ввода/вывода могут быть указаны в комментариях.

Выполнение операций над данными В блоке операций обычно размещают одно или несколько (ГОСТ не запрещает) операций присваивания, не требующих вызова внешних функций.

Блок, иллюстрирующий ветвление алгоритма Блок в виде ромба имеет один вход и несколько подписанных выходов. В случае, если блок имеет 2 выхода (соответствует оператору ветвления), на них подписывается результат сравнения — «да/нет». Если из блока выходит большее число линий (оператор выбора), внутри него записывается имя переменной, а на выходящих дугах — значения этой переменной.

Вызов внешней процедуры Вызов внешних процедур и функций помещается в прямоугольник с дополнительными вертикальными линиями.

Начало и конец цикла Символы начала и конца цикла содержат имя и условие. Условие может отсутствовать в одном из символов пары. Расположение условия, определяет тип оператора, соответствующего символам на языке высокого уровня — оператор с предусловием (while) или постусловием (do … while).

Подготовка данных Символ «подготовка данных» в произвольной форме (в ГОСТ нет ни пояснений, ни примеров), задает входные значения. Используется обычно для задания циклов со счетчиком.

Соединитель В случае, если блок-схема не умещается на лист, используется символ соединителя, отражающий переход потока управления между листами. Символ может использоваться и на одном листе, если по каким-либо причинам тянуть линию не удобно.

Комментарий Комментарий может быть соединен как с одним блоком, так и группой. Группа блоков выделяется на схеме пунктирной линией.

Примеры блок-схем

В качестве примеров, построены блок-схемы очень простых алгоритмов сортировки, при этом акцент сделан на различные реализации циклов, т.к. у студенты делают наибольшее число ошибок именно в этой части.

Сортировка вставками

Массив в алгоритме сортировки вставками разделяется на отсортированную и еще не обработанную части. Изначально отсортированная часть состоит из одного элемента, и постепенно увеличивается.

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

Блок-схема алгоритма сортировки вставками

В приведенной блок-схеме для организации цикла используется символ ветвления. В главном цикле (i Блок-схема алгоритма сортировки пузырьком

На блок-схеме показано использование символов начала и конца цикла. Условие внешнего цикла (А) проверяется в конце (с постусловием), он работает до тех пор, пока переменная hasSwapped имеет значение true. Внутренний цикл использует предусловие для перебора пар сравниваемых элементов. В случае, если элементы расположены в неправильном порядке, выполняется их перестановка посредством вызова внешней процедуры (swap). Для того, чтобы было понятно назначение внешней процедуры и порядок следования ее аргументов, необходимо писать комментарии. В случае, если функция возвращает значение, комментарий может быть написан к символу терминатору конца.

Сортировка выбором

В сортировке выбором массив разделяется на отсортированную и необработанную части. Изначально отсортированная часть пустая, но постепенно она увеличивается. Алгоритм производит поиск минимального элемента необработанной части и меняет его местами с первым элементом той же части, после чего считается, что первый элемент обработан (отсортированная часть увеличивается).

Блок-схема сортировки выбором

На блок-схеме приведен пример использования блока «подготовка», а также показано, что в ряде случаев можно описывать алгоритм более «укрупнённо» (не вдаваясь в детали). К сортировке выбором не имеют отношения детали реализации поиска индекса минимального элемента массива, поэтому они могут быть описаны символом вызова внешней процедуры. Если блок-схема алгоритма внешней процедуры отсутствует, не помешает написать к символу вызова комментарий, исключением могут быть функции с говорящими названиями типа swap, sort, … .

На блоге можно найти другие примеры блок-схем:

Часть студентов традиционно пытается рисовать блок-схемы в Microsoft Word, но это оказывается сложно и не удобно. Например, в MS Word нет стандартного блока для терминатора начала и конца алгоритма (прямоугольник со скругленными краями, а не овал). Наиболее удобными, на мой взгляд, являются утилиты MS Visio и yEd [5], обе они позволяют гораздо больше, чем строить блок-схемы (например рисовать диаграммы UML), но первая является платной и работает только под Windows, вторая бесплатная и кроссплатфомренная. Все блок-схемы в этой статье выполнены с использованием yEd.

Нужны ли блок-схемы? Альтернативы

Частные конторы никакие блок-схемы не используют, в книжках по алгоритмам [6] вместо них применяют словесное описание (псевдокод) как более краткую форму. Возможно блок-схемы применяют на государственных предприятиях, которые должны оформлять документацию согласно требованиям ЕСПД, но есть сомнения — даже для регистрации программы в Государственном реестре программ для ЭВМ никаких блок-схем не требуется.

Тем не менее, рисовать блок-схемы заставляют школьников (примеры из учебников ГОСТ не соответствуют) — выносят вопросы на государственные экзамены (ГИА и ЕГЭ), студентов — перед защитой диплом сдается на нормоконтроль, где проверяется соответствие схем стандартам.

Разработка блок-схем выполняется на этапах проектирования и документирования, согласно каскадной модели разработки ПО, которая сейчас почти не применяется, т.к. сопровождается большими рисками, связанными с ошибками на этапах проектирования.

Появляются подозрения, что система образования прогнила и отстала лет на 20, однако аналогичная проблема наблюдается и за рубежом. Международный стандарт ISO 5807:1985 мало чем отличается от ГОСТ 19.701-90, более нового стандарта за рубежом нет. Там же производится множество программ для выполнения этих самых схем — Dia, MS Visio, yEd, …, а значит списывать их не собираются. Вместо блок-схем иногда применяют диаграммы деятельности UML [6], однако удобнее они оказываются, разве что при изображении параллельных алгоритмов.

Периодически поднимается вопрос о том, что ни блок-схемы, ни UML не нужны, да и документация тоже не нужна. Об этом твердят программисты, придерживающиеся методологии экстремального программирования (XP) [7], ходя даже в их кругу нет единого мнения.

В ряде случаев, программирование невозможно без рисования блок-схем, т.к. это один процесс — существуют визуальные языки программирования, такие как ДРАКОН [8], кроме того, блок-схемы используются для верификации алгоритмов (формального доказательства их корректности) методом индуктивных утверждений Флойда [9].

В общем, единого мнения нет. Очевидно, есть области, в которых без чего-то типа блок-схем обойтись нельзя, но более гибкой альтернативы нет. Для формальной верификации необходимо рисовать подробные блок-схемы, но для проектирования и документирования такие схемы не нужны — я считаю разумным утверждение экстремальных программистов о том, что нужно рисовать лишь те схемы, которые помогают в работе и не требуют больших усилий для поддержания в актуальном состоянии [10].

Диаграмма Вороного и её применения

Доброго всем времени суток, уважаемые посетители сайта Хабрахабр. В данной статье я бы хотел рассказать вам о том, что такое диаграмма Вороного (изображена на картинке ниже), о различных алгоритмах её построения (за , — пересечение полуплоскостей, — алгоритм Форчуна) и некоторых тонкостях реализации (на языке C++).

Также будет рассмотрено много интересных применений диаграммы и несколько любопытных фактов о ней. Будет интересно!

План статьи:

Стоит отметить, что в данной статье будут рассматриваться только алгоритмы построения диаграммы Вороного на плоскости. Попутно будут рассмотрены некоторые другие алгоритмы, необходимые для построения диаграммы — алгоритм определения точки пересечения двух отрезков, алгоритм О`Рурка пересечения двух выпуклых многоугольников, алгоритм построения «береговой линии».

Необходимые понятия и определения

Сразу скажу, что всё, что будет дальше происходить, находится на плоскости.

Что ж, перед тем, как начать разбираться, что это такое — диаграмма Вороного, напомню некоторые понятия нужных нам геометрических объектов (предполагается, однако, что вы уже знакомы с определениями точки, прямой, луча, отрезка, многоугольника, вершины и ребра многоугольника, вектора и интуитивного понятия разбиения плоскости):

Простой многоугольник — это многоугольник без самопересечений. Мы будем рассматривать только простые многоугольники.

Невыпуклый многоугольник — это многоугольник, в котором найдутся такие две вершины, что через них проводится прямая, пересекающая данный многоугольник где-либо ещё, кроме ребра, соединяющего эти вершины (см. картинку),

Выпуклый многоугольник — это многоугольник, у которого продолжения сторон не пересекают других его сторон (см. картинку). С другими вариантами определений можно ознакомиться на википедии.

Именно из выпуклых многоугольников и будет состоять диаграмма. Почему именно из выпуклых? Потому что они являются ничем иным, как пересечением полуплоскостей (как мы увидим чуть позже), которые являются выпуклыми фигурами, а вот почему пересечение выпуклых фигур — выпуклая фигура, предложу вам узнать самим (доказательство есть, например, в книге [2]).

Раз уж я начал говорить про полуплоскости, то можно плавно перейти и к самой диаграмме — она состоит из так называемых локусов — областей, в которых присутствуют все точки, которые находятся ближе к данной точке, чем ко всем остальным. В диаграмме Вороного локусы являются выпуклыми многоугольниками.

Как строить локус? По определению он будет строиться так: пусть дано множество из n точек, для которого мы строим диаграмму. Возьмём конкретную точку p, для которой строим локус, и ещё одну точку из данного нам множества — q (не равную p). Проведём отрезок, соединяющий эти две точки, и проведём прямую, которая будет являться серединным перпендикуляром данного отрезка. Эта прямая делит плоскость на две полуплоскости — в одной лежит точка p, в другой лежит точка q. В данном случае локусами этих двух точек являются полученные полуплоскости. То есть для того, чтобы построить локус точки p, нужно получить пересечение всех таких полуплоскостей (то есть на месте q побывают все точки данного множества, кроме p).

Точку, для которой строится локус, называют сайтом (site). На следующей картинке локусы помечены разными цветами.

Алгоритмы построения диаграммы как раз и есть не что иное, как алгоритмы построения этих самых локусов для всех точек из заданного набора. Локусы в данной задаче также называют многоугольниками Вороного или ячейками Вороного.

Наконец, сформулируем определение диаграммы Вороного n точек на плоскости (n — натуральное) — это разбиение плоскости, состоящее из n локусов (для каждой точки по локусу). Опять же, другой вариант определения можно найти на википедии.

Кстати, вот сайт с интерактивным цветным визуализатором диаграммы Вороного, можно самому нажимать на область и залипать видеть, как строится диаграмма.

Если интересно, как появилась диаграмма и почему она носит фамилию Вороного, то вам стоит взглянуть под спойлер ниже.

Немного истории

(материал взят с этого сайта)
Вообще, первое использование этой диаграммы встречается в труде Рене Декарта (1596-1650) «Начала философии» (1644). Декарт предложил деление Вселенной на зоны гравитационного влияния звезд.

Только спустя два века, известный немецкий математик Иоганн Петер Густав Лежён-Дирихле (1805 — 1859) ввел диаграммы для двух- и трехмерного случаев. Поэтому их иногда называют диаграммами Дирихле.

Ну а уже в 1908 году русский математик Георгий Феодосьевич Вороной (16(28) апреля 1868 — 7(20) ноября 1908) описал эту диаграмму для пространств бОльших размерностей, с тех пор диаграмма носит его фамилию. Вот его краткая биография (взято из википедии):

Георгий Феодосьевич Вороной родился в деревне Журавка Полтавской губернии (ныне Черниговская область). С 1889 года обучался в Санкт-Петербургском университете у Андрея Маркова. В 1894 году защитил магистерскую диссертацию «О целых числах, зависящих от корня уравнения третьей степени». В том же году был избран профессором Варшавского университета, где изучал цепные дроби. У Вороного обучался Вацлав Серпинский. В 1897 году Вороной защитил докторскую диссертацию «Об одном обобщении алгоритма непрерывных дробей», удостоенную премии имени Буняковского.

Алгоритмы построения

Научимся строить диаграмму Вороного. Мы рассмотрим 4 алгоритма, 2 из которых подробно (1 с реализацией, полной реализации алгоритма Форчуна будет посвящена отдельная статья), ещё 2 кратко (и без реализации):

  1. Алгоритм построения диаграммы Вороного «в лоб». Сложность: ;
  2. Алгоритм построения диаграммы Вороного путём пересечения полуплоскостей. Сложность: ;
  3. Алгоритм Форчуна построения диаграммы Вороного на плоскости. Сложность: ;
  4. Рекурсивный алгоритм построения диаграммы Вороного. Сложность: .

После описания некоторых алгоритмов будет приведена его реализация на языке C++. Для реализации использовалась написанная нами библиотека SplashGeom © — ссылка на github, в которой есть всё необходимое для реализации многих алгоритмов вычислительной геометрии на плоскости и некоторых в пространстве. Прошу не судить строго данную библиотеку, она ещё находится в стадии активной разработки и улучшения, однако все замечания будут услышаны.

Если же вам интересны другие реализации, то вот ещё некоторые:

Алгоритм построения диаграммы Вороного «в лоб» за

Здесь идея в том, чтобы пересекать не полуплоскости, а именно серединные перпендикуляры отрезков (потому что это проще, согласитесь), соединяющих данную точку со всеми другими точками. То есть мы, следуя определению ячейки Вороного, будем строить локус для точки p так:

  1. Получаем n-1 прямую (серединные перпендикуляры), так как мы провели серединные перпендикуляры всех отрезков, соединяющих данную точку p с остальными;
  2. Пересекаем попарно все прямые, получаем точек пересечения (потому что каждая прямая может пересечь все другие, в «худшем случае»);
  3. Проверяем все эти точек на принадлежность каждой из n-1 полуплоскостей, то есть получаем уже асимптотику . Соответственно те точки, которые принадлежат всем полуплоскостям, и будут вершинами ячейки Вороного точки p;
  4. Проделываем первые три шага для всех n точек, получаем итоговую асимптотику .

С алгоритмом также можно ознакомиться на e-maxx.ru.

При желании Вы самостоятельно можете реализовать этот алгоритм с помощью SplashGeom ©. В данной статье его реализация не приводится, потому как данный алгоритм на практике сильно уступает хотя бы следующему…

Алгоритм построения диаграммы Вороного путём пересечения полуплоскостей за

Этот алгоритм уже можно использовать на практике, так как он не имеет столь большой вычислительной сложности. Для него нам потребуется: уметь пересекать отрезки и прямые, уметь пересекать выпуклые многоугольники, уметь пересекать полуплоскости, уметь объединять полученные локусы в диаграмму.

Алгоритм

Реализация

Основная загвоздка здесь, я считаю, реализовать нормальное пересечение выпуклых многоугольников, потому как там есть неприятные вырожденные случаи (совпадение вершин и/или сторон многоугольников; в случае пересечения многоугольника с самим собой надо неплохо подумать, чтобы адаптировать алгоритм О`Рурка для корректной работы в этом случае).

Сразу скажу, что мы ограничиваем всю область действий ограничивающим прямоугольником — полуплоскости будут отсекать от него части, которые мы и пересечём друг с другом. Это решает проблему бесконечных ячеек в диаграмме.

Пересечение прямых и отрезков

Причём нам нужны именно точки пересечения, а не просто определение его наличия. В SplashGeom © это есть — вот, к примеру, реализация пересечения прямых и отрезков:

Пересечение выпуклых многоугольников

Теперь реализуем пересечение многоугольников. Можно, конечно, делать это за , где n и m — количество вершин первого и второго многоугольника соответственно — пересекать каждую сторону первого многоугольника с каждой стороной из второго, записывая точки пересечения, а также проверять точки на принадлежность другому многоугольнику, но мы, дабы достичь лучшей скорости, будем пересекать по алгоритму О`Рурка (оригинальное описание алгоритма — [3]).

Также с одним из вариантов его описания можно ознакомиться на algolist.ru. У нас же реализация основана на описании алгоритма в книге [1] (стр. 334), с некоторыми дополняющими идеями. Сразу отмечу, что данная реализация не учитывает случаи, когда у многоугольников есть общие стороны (как отмечено в книге [1], этот случай требует отдельного рассмотрения), однако случаи с общими вершинами работают корректно.

Под спойлером ниже можно увидеть общее описание алгоритма.

Ну а в SplashGeom © это выглядит так:

Надеюсь, данное описание и код будут вам полезны.

Пересечение полуплоскостей

Итак, у нас есть всё необходимое для построения пересечения полуплоскостей. Что ж, сделаем это, да сделаем не просто, а по-умному — в силу ассоциативности операции пересечения полуплоскостей, мы можем пересекать их в любом порядке, а значит пересечём две плоскости, потом пересечём ещё две, а потом пересечём их пересечения, это ведь уже быстрее, чем пересекать все по-отдельности.

Так что тут целесообразно использовать рекурсию (сразу настроение испортилось) — её работа здесь вполне понятна, сами посмотрите:

Добавление локуса в диаграмму

Теперь мы имеем многоугольник Вороного данной точки, пора добавить его в диаграмму. Проблем с этим здесь особо не возникает, потому как мы получаем области в произвольном порядке, и между собой они никак не связаны (в отличие от реализации в алгоритме Форчуна, где можно перейти на соседний локус по указателю на ребро):

Так, мы научились строить диаграмму Вороного за , она имеет вид вектора (списка) локусов. Недостаток данного решения — информации о соседях не получить (возможно, этот недостаток можно ликвидировать улучшенной реализацией).

Далее будет описан алгоритм Форчуна с использованием заметающей прямой и «береговой линии» (готовьте купальники и плавки — идём на пляж). По моему мнению, это самый приемлемый вариант, если вы хотите реализовать построение диаграммы Вороного и строить её со «скоростью» света .

Алгоритм Форчуна построения диаграммы Вороного за

В 1987 году Стив Форчун (Steve Fortune) предложил алгоритм построения диаграммы за . Конечно, он является не единственным алгоритмом построения с такой асимптотикой, но он достаточно понятен и не очень сложен в реализации (да и, к тому же, очень красив и математичен!), поэтому я выбрал именно его.

Материалы по алгоритму Форчуна можно найти тут, здесь, вот здесь и ещё вот здесь.

Кстати, рассмотрению данного алгоритма уже была посвящена статья на Хабрахабре.

Итак, основная идея алгоритма — это так называемая заметающая прямая (ЗП) (sweep line). Она применяется во многих алгоритмах вычислительной геометрии, потому что позволяет удобно моделировать движение прямой по некоторому множеству объектов (например, в алгоритме пересечения n отрезков тоже используется sweep line).

Перед тем, как начать говорить про то, как и что мы будем делать, давайте посмотрим, как движется sweep line (взято отсюда):

Красиво, не правда ли? В реализации всё примерно так же, только ЗП обычно движется сверху вниз, а не слева направо, и на самом деле всё не так плавно, а происходит от события к событию (см. ниже), то есть дискретно.

Суть алгоритма

Есть n сайтов (точек на плоскости). Есть заметающая прямая, которая двигается (например) «сверху вниз», то есть от сайта с наибольшей ординатой к сайту с меньшей (от события к событию, если быть точным). Сразу стоит отметить, что влияние на построение диаграммы оказывают только те сайты, которые находятся выше или на заметающей прямой.

Когда ЗП попадает на очередной сайт (происходит событие точки (point event)), создаётся новая парабола (arch), фокусом которой является данный сайт, а директрисой — заметающая прямая (про параболу на википедии). Эта парабола делит плоскость на две части — «внутренняя» область параболы соответствует точкам, которые сейчас ближе к сайту, а «внешняя» область — точкам, которые ближе к sweep line, ну а точки, лежащие на параболе — равноудалены от сайта и ЗП. Парабола будет меняться в зависимости от положения ЗП к сайту — чем дальше ЗП уходит от сайта вниз, тем больше расширяется парабола, однако в самом начале она вообще является отрезком («направленным» вверх).

Далее парабола расширяется, у неё появляются две контрольные точки (break points) — точки её пересечения с остальными параболами («береговой линией»). В «береговой линии» мы храним дуги парабол от одной точки пересечения их друг с другом до другой, так и получается beach line. По сути, в этом алгоритме мы моделируем движение этой «береговой линии». потому как эти самые break point`ы движутся аккурат по рёбрам ячеек Вороного (ведь получается, что контрольные точки равноудалены от обоих сайтов, которым соответствуют эти параболы, да ещё и от ЗП).

И как раз-таки в тот момент, когда две контрольные точки — по одной из разных парабол — «встречаются», то есть как бы превращаются в одну, эта точка и становится вершиной ячейки Вороного (происходит событие круга (circle event)), причём в это время та дуга, которая находилась между этими двумя точками — «схлопывается» и удаляется из «береговой линии». Далее мы просто соединяем эту точку с предыдущей соответствующей ей и получаем ребро ячейки Вороного.

Алгоритм

Итак, при движении sweep line вниз мы встречаемся с двумя типами событий:

Событие точки (point event)

Событие точки — это попадание ЗП на один из сайтов, поэтому мы создаём новую параболу, соответствующую данному сайту, а также добавляются две контрольные точки (break points) (на самом деле сначала — одна, а при расширении арки уже две) — точки пересечения этой параболы с береговой линией (то есть с фронтом уже существующих парабол). Стоит отметить, что в данном алгоритме парабола (а точнее её часть, принадлежащая «береговой лини» — арка) «вставляется в береговую линию» только в случае события точки, то есть новая арка может появиться только при обработке события точки.

Кстати, на следующих картинках видно, почему объединения таких «кусков парабол» называют «береговой линией».

Событие круга (circle event)

Событие круга — это возникновение новой вершины ячейки Вороного вместе с удалением одной арки, потому что возникновение новой вершины диаграммы здесь означает, что было три арки, левая, средняя и правая, средняя «схлопывается» вследствие сближения левой и правой точек арок и получается новая вершина диаграммы Вороного. Стоит отметить, что в данном алгоритме парабола (арка) удаляется из «береговой линии» только в случае события круга, то есть арка может удалиться только при обработке события круга.

Есть теорема, в которой говорится, что вершина диаграммы Вороного всегда лежит на пересечении ровно трёх рёбер диаграммы, и есть следствие из этой теоремы, которое гласит, что вершина диаграммы является центром окружности, проходящей через три сайта и расстояние от этой точки до заметающей прямой тоже равно радиусу этой окружности (это свойство точек, лежащих на «береговой линии»). Это — ключевой момент, потому что именно когда самая нижняя точка окружности, проходящей через три сайта, лежит ниже или на заметающей прямой, мы пушим в очередь событий событие круга с этой самой нижней точкой, потому что когда прямая на неё попадёт, мы получим вершину диаграммы Вороного.

Важно, что с любым событием (точки или круга) связана одна конкретная арка, и наоборот. Это пригодится при обработке событий. Также надо не забыть, что нужно вовремя добавлять рёбра в РСДС (DCEL ) (пункт 1 в структурах, см. ниже), так что надо понимать связь арок с рёбрами.

Таким образом, движение прямой дискретно — прямая в любой момент времени либо на сайте, либо в нижней точке окружности, проходящей через три сайта, центр которой — новая вершина диаграммы Вороного. Прекрасно.

    Создаём очередь (с приоритетом) событий, изначально инициализируя событиями точки — данным множеством сайтов (ведь каждому сайту соответствует событие точки);

Пока очередь не пуста:

а). Берём из неё событие;
б). Если это — событие точки, то обрабатываем событие точки;
в). Если это — событие круга, то обрабатываем событие круга;

  • Закончить все оставшиеся рёбра (поработать с border_box).
  • Реализация

    Реализация алгоритма Форчуна будет рассмотрена подробно в отдельной статье, однако здесь приводятся некоторые наработки, которые могут помочь в его понимании.

    Необходимые структуры

    Для реализации данного алгоритма нам понадобятся несколько структур (классов), а именно:

    Вся логика и сложность в HandlePointEvent() и HandleCircleEvent(), им и будет посвящена отдельная статья, далее же приведу некоторые вспомогательные функции, которые потом помогут в реализации.

    Вспомогательные функции
    Пересечение парабол (арок)

    Нам нужно уметь получать пересечение двух парабол (арок) в зависимости от положения ЗП. Уравнение параболы с фокусом в точке x’ и y’ и директрисой, положение которой по оси y равно l, задаётся следующим уравнением (его можно вывести):

    Кстати, дробь перед скобкой — это фокальный параметр данной параболы. Отсюда мы можем «вытащить» соответствующие коэффициенты уравнения параболы и решить систему из двух нелинейных уравнений простым способом — вычтем одно из другого, а потом подставим найденные корни в первое, получим две точки. Нас интересует та точка, которая ниже (то есть с меньшей ординатой), потому что высокая точка лежит за «береговой линией». Описанные действия отражаются в следующем коде:

    Построение окружности по трём точкам

    При обработке события круга нам понадобится определять центр и самую нижнюю точку окружности, построенной по фокусам трёх арок (сайтам). Есть некоторые аналитические алгоритмы построения окружности по трём точкам (под построением мы понимаем получение её центра и радиуса), у нас в программе это сделано так (спасибо алголисту) — соединяем отрезками первые две точки и вторые две точки. Центр лежит на пересечении серединных перпендикуляров, радиус — расстояние от центра до любой из трёх точек. Быстро и красиво:

    Обработка события точки

    Событие точки — это когда мы вытащили из очереди PointEvent. Что в нём есть? В нём есть только сайт, с которым ассоциируется это событие.

    Рейтинг надежности площадок для торговли бинарных опционов:
    • Бинариум
      Бинариум

      1 место! Лидер на рынке — самый честный брокер бинарных опционов!
      Идеально для новичков — предоставляется бесплатное онлайн-обучение и демо-счет!
      Получите бонус за регистрацию по ссылке:

    Что мы делаем при его обработке? Мы добавляем новую арку в «береговую линию», настраивая в дереве все связи «как надо», и проверяем, не появилось ли событие круга в одном из трёх возможных случаев — нам нужно проверить все случаи, в которых может участвовать новый сайт.

    Что мы делаем при добавлении арки? Мы ищем для неё место в нашем двоичном дереве «береговой линии» (по координате x), затем вставляем её.

    Что мы делаем при вставке? Мы нашли указатель на арку, с которой новая имеет пересечение в двух точках (случай с попаданием точки пересечения ровно на одну из контрольных точек рассматривается отдельно — там пересечение будет с двумя параболами — слева и справа).

    То есть мы берём эту арку, которая «разбивается», и вместо неё вставляем аж 5 узлов (был 1, стало 5, да) — arch1, bp1, arch2, bp2, arch3. Arch1 — это левый кусок арки, которую пересекает новая, то есть это кусок слева от левого break point`а, bp1 — левый break point (левое пересечение новой арки), arch2 — это новая арка собственной персоной, bp2 — правый break point (правое пересечение новой арки), arch3 — это правый кусок арки, которую пересекает новая.

    Стоит отметить, что событие точки даёт начало новому ребру (или рёбрам, есть случаи) диаграммы Вороного.

    Один из возможных вариантов добавления новой арки в «береговую линию» представлен в этой статье на Хабре, наш же вариант описан выше, и больше похож на тот, который предложен здесь.

    Обработка события круга

    Событие круга — это когда мы вытащили из очереди CircleEvent.

    Что в нём есть? В нём есть точка — это самая нижняя точка некоторой окружности, которая проходит через три каких-то сайта, и арка, которую следует удалить. В дереве есть две её контрольные точки и она сама, контрольные точки в итоге превратятся в одну, а арку нужно аккуратно удалить из дерева, перестроив все «связи родителей-детей». По сути, обработка этого события заменяет в дереве три узла на один (два break point`а и арку на один break point).

    Стоит отметить, что событие круга завершает два ребра диаграммы Вороного, то есть при обработке этого события рёбра будут завершаться.

    Также скажу, что важной частью обработки событий является то, как мы следим за ростом рёбер, добавлением их в список и завершением рёбер, то есть за тем, чтобы в итоге они все были «закончены», и либо были конечны, либо упирались в ограничивающий прямоугольник.

    Небольшой анализ результата

    Причём если у ребра «нулевой» сайт, то мы оказались на «граничном сайте» — сайте с «бесконечным» локусом. Хмм, но ведь это позволит нам построить выпуклую оболочку начального множества точек за в итоге, здорово.

    Ну и вообще, РСДС — это, по сути, граф, так что можно продолжать работать с этим списком во многих алгоритмах на графах.

    Рекурсивный алгоритм построения диаграммы Вороного за

    Данный алгоритм приводится в книге [1] (стр. 260), здесь я приведу только сам алгоритм построения, поскольку данный вариант мы не реализовывали, хотя он является хорошей аналогией алгоритму Форчуна.

    Алгоритм

    1. Делим всё множество сайтов S на две примерно равные части (может быть нечётное количество точек) S1 и S2;
    2. Рекурсивно строим диаграммы Вороного для S1 и S2;
    3. Объединить полученные диаграммы и получить диаграмму для S.

    Общее описание алгоритма не сложное, однако в алгоритме есть свои тонкости, с которыми Вы можете ознакомиться в указанной книге.

    Применения

    Исчерпывающий список всех применений диаграммы Вороного находится здесь, я же упомяну некоторые из них, показавшиеся мне наиболее интересными (многие сведения взяты из [1]):

    В программировании, разработке игр и картографии

    В вычислительной геометрии диаграмма Вороного нужна прежде всего для решения задачи близости точек, а точнее, особый выигрыш диаграмма даёт в решении задачи ВСЕ ближайшие соседи (не те, которые громко включают музыку, а хотя..), потому как аналогичные ей способы не так просты ([1]). Используя диаграмму Вороного можно построить выпуклую оболочку за (смотреть на «лучевые» рёбра, находить сайты, к которым они принадлежат, и включать их в оболочку).

    Также существует важная связь диаграммы Вороного с триангуляцией Делоне, которая позволяет строить одно по другому за , потому как они являются двойственными друг к другу (соединяем рёбрами соседние сайты, в итоге получим триангуляцию Делоне — викиконспекты).

    Пример использования диаграммы Вороного в геймдеве можно найти, например, в этой статье — здесь система навигации в игровом движке основана на диаграмме.

    Не исключено, и даже вероятно, что различный геолокационный софт использует диаграммы Вороного. Геолокационные рекомендательные системы могут использовать диаграмму Вороного для определения, например, ближайшего к вам продуктового магазина, для различного поиска и анализа местоположения.

    Здесь же можно упомянуть и применение диаграммы в картографии — для очерчивания границ регионов и дальнейшего анализа на их основе. Да и вообще, любые географические диаграммы, показывающие распределение чего либо, можно наглядно проиллюстрировать с помощью раскрашенных диаграмм Вороного, и там будет виден переход нужного нам показателя (например, температуры):

    Ну и, конечно, можно делать различные фильтры-обработчики фото с помощью диаграммы Вороного, получая некую «мозаику».

    Но это только начало её применения.

    В архитектуре и дизайне

    Весьма логично, что людям в голову пришла идея использовать диаграмму Вороного в архитектуре и дизайне, поскольку она сама по себе является красивым рисунком, своего рода «геометрической паутиной», так что есть много случаев применения её в качестве одного из основных элементов композиции или даже каркаса всего творения. Примеры:

    В археологии

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

    — что вполне логично, ведь обычно за любое «выживание» бьются именно соседствующие регионы.

    В моделировании и распознавании

    В этой статье 3D-диаграмма Вороного не рассматривается, однако она имеет многие приложения в физике и 3D-моделировании объектов. Разного рода сетки (и скелеты) объектов в пространстве можно построить с помощью диаграммы Вороного (однако чаще с помощью триангуляции Делоне).

    3D-сканирование (и компьютерное зрение (computer vision)) различных объектов тоже может использовать диаграмму Вороного и триангуляцию Делоне, также это тесно связано с робототехникой — движение робота с учётом препятствий на пути.

    В биологии и химии

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

    Вот ещё одна интересная статья про применение диаграммы Вороного.

    Интересные факты

    Природа — удивительная вещь, ведь оказывается, что окрас жирафа фактически имеет вид диаграммы Вороного. Это видно невооружённым глазом:

    Также примечательно и следующее наблюдение, которое показывает, что диаграмму можно увидеть даже на листьях деревьев:

    Кстати, чуть меньше, чем год назад, с диаграммой Вороного также был связан один инцидент — здесь она использовалась в логотипе проекта «Новая Москва».

    И — напоследок — видео, в котором видно, как диаграмма появляется при росте окружностей с центрами в сайтах:

    Здесь можно провести аналогию с распространением пожара, имеющего несколько очагов возгорания.

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

    Спасибо за внимание!

    Список литературы

    [1] Препарата Ф., Шеймос М. Вычислительная геометрия. Введение (1989)
    [2] Александров А. Д., Вернер А. Л., Рыжик В. И. Стереометрия. Геометрия в пространстве
    [3] Joseph O’Rourke. Computational Geometry in C

    » Статью подготовил студент 1-го курса ФИВТ МФТИ Захаркин Илья.
    » В написании библиотеки также помогали студентки 1-го курса ФИВТ МФТИ Кириленко Елена и Касимова Надежда.
    » В тестировании библиотеки помогал Ярослав Спирин.
    » Отдельная благодарность менторам Гадельшину Ильнуру и Гафарову Рустаму.

    Разрабатываем алгоритмы действий и создаем блок-схемы

    Разрабатываем алгоритмы действий и создаем блок-схемы

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

    Такое поведение можно называть по-разному, смотря в каком контексте оно рассматривается. Если рассмотреть с позиции эффективности деятельности, то эти действия можно назвать привычками или навыками. Если рассматривать с точки зрения отображения процесса, то описание последовательности действий, строгое исполнение которых приводит к решению поставленных задач за определенное количество шагов, называют алгоритмом действий.

    Как создаются алгоритмы действий?

    Мы постоянно сталкиваемся с этим в обычной жизни. Какие действия мы совершаем, чтобы пополнить счет своего мобильного телефона? Каждый из нас – разные. Так как способов пополнения счета несколько, следовательно мы все по-разному это делаем. Результат, правда всегда один получается – появление средств на телефоне.

    Или еще пример: чтобы скопировать картинку или текст, нажимаем правой кнопкой мыши на картинку, затем выбираем “Копировать”, помещаем в нужное место, нажимаем правой кнопкой ” Вставить”, и результат достигнут.

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

    Опишите последовательность действий – это запоминается

    Создать алгоритм действий можно, описав или изобразив его последовательность. Знают ли все, что надо сделать, чтобы посадить дерево? Возможно, основные шаги понятны всем, но вот когда деревце поливать, перед посадкой или после, помнит не каждый. Созданный алгоритм позволит все действия выполнить в правильной последовательности.

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

    Алгоритм действий в графике – это блок-схема

    Если изобразить алгоритмы действий в графическом варианте, с помощью геометрических фигур с линиями-связями, показывающими порядок выполнения действия, то мы получим блок-схему. Блок-схема намного превосходит правила, инструкции, и записанные по порядку алгоритмы действий, по своей наглядности и читаемости.

    Представьте, что вам нужно чему-то научить другого человека. Вы отлично знаете все действия в определенной последовательности. Ваша задача – показать, как это нужно делать и передать свои знания так, чтобы другой человек их запомнил и знал так же, как и вы. Устная передача знаний допускает импровизации и некоторый произвол. Самым лучшим способом будет блок-схема, в которой объясняется последовательность и возможные варианты действий. В качестве примера – веселое руководство по изучению блог-схем:

    Лучшим условием для получения результата будет повторяемость действий. Это однозначно влияет на скорость достижения результата в будущем. Чем чаще вам придется повторять одни и те же действия, тем быстрее вы научитесь выполнять последовательность действий, а значит в каждый последующий раз, вам потребуется меньше времени на выполнение.

    Блок-схемы применяются в продажах

    В продажах такое обучение с помощью разработки алгоритмов и изображения их в виде блок-схем имеет большое распространение. Чаще всего их используют в телефонных сценариях разговоров в call-центрах и для “холодных” звонков. Корпоративная культура набирает обороты, поэтому многие компании уже не позволяют сотрудникам нести “отсебятину”, даже талантливую, а предлагают действовать им по заранее разработанному сценарию, представляя “лицо фирмы” на различных этапах. Эффект появляется буквально после нескольких дней действий “по бумажке”. Со временем, многое из описанных алгоритмов запоминается сотрудником, и в дальнейшем он свободно может общаться, не опасаясь того, в какую сторону может уйти разговор.

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

    Стоит попробовать научиться действовать по подобным блок-схемам. Ведь впервые встречаясь с непонятным поначалу обилием действий и задач, думаешь о том, как тебе не хватает разработанной блок-схемы. После долгих мучений не выдерживаешь, и начинаешь разрабатывать и создавать самостоятельно. Эффективные люди не любят простоев в делах. А блок-схемы значительно упрощают жизнь и позволяют разобраться в решении сложных задач.

    Сервисы для разработки блок-схем

    В интернете есть сервисы, которые могут помочь вам создавать такие блок-схемы. Один из них – [urlspan]Сacoo[/urlspan]. С его помощью вам легко удастся превращать ваши алгоритмы в различные диаграммы, блок-схемы и графики. Вы увидите, что это очень приятное и радостное занятие – преобразовывать то, что вам известно, в науку для других людей.

    На этом онлайн-сервисе – хорошее настроение вам обеспечено. На первоначальном этапе можно воспользоваться возможностями бесплатной учетной записи, а в будущем за доступ нужно будет платить. Естественно, что бесплатный доступ имеет ограничения по сравнению с платными. Но для изучения и первых шагов, функционала вполне достаточно.

    Разработав алгоритмы действий и преобразовав их в блок-схемы с помощью Cacoo, вы сможете надолго создать хорошее настроение не только себе, но и другим людям, постигающим азы.

    Создавайте игровые блок-схемы для своих детей

    Подводя итог вышесказанному отмечу, что теперь вы сможете использовать алгоритмы действий и блок-схемы в различных жизненных ситуациях. Даже ваши дети с огромным удовольствием станут выполнять не самые интересные обязанности, следуя понятным подсказкам. Если будут идеи, где и как можно применять алгоритм действий, поделитесь в комментариях, уважаемые читатели. Очень хотелось бы узнать про ваши алгоритмы.

    Моя блок-схема

    Вот какая блок-схема у меня получилась в первый раз. Для того, чтобы увеличить изображение, нажмите на него. После перехода на Cacoo, под записью “просмотр фигуры”, нажимайте на картинку. Она откроется в большом окне. Удачи!

    Успевайте больше за меньшее время вместе с “Копилкой эффективных советов”.

    Список надежных брокеров бинарных опционов на русском языке:
    • Бинариум
      Бинариум

      1 место! Лидер на рынке — самый честный брокер бинарных опционов!
      Идеально для новичков — предоставляется бесплатное онлайн-обучение и демо-счет!
      Получите бонус за регистрацию по ссылке:

    Добавить комментарий