Скачать презентацию Алгоритмы. Методы построения и анализа алгоритмов. Сложность алгоритмов. Скачать презентацию Алгоритмы. Методы построения и анализа алгоритмов. Сложность алгоритмов.

Информационные технологии.ppt

  • Количество слайдов: 71

Алгоритмы. Методы построения и анализа алгоритмов. Сложность алгоритмов. Мясников Никита Владимирович Алгоритмы. Методы построения и анализа алгоритмов. Сложность алгоритмов. Мясников Никита Владимирович

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

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

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

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

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

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

Овал Начало или конец Параллелограмм Ромб Ввод или вывод данных Принятие решения Вспомогательный алгоритм Овал Начало или конец Параллелограмм Ромб Ввод или вывод данных Принятие решения Вспомогательный алгоритм Выполнение действия

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

Следуя из определений, алгоритм –это процедура, которая: Применяется к строго определённым исходным данным А. Следуя из определений, алгоритм –это процедура, которая: Применяется к строго определённым исходным данным А. Ее нельзя применить к другому типу данных, она либо будет неспособна с ними работать, либо выдаст результат не поддающийся анализу в соответствии с нашими ожиданиями. Разложена на отдельные простые шаги; каждый шаг состоит в непосредственной обработке возникшего к этому шагу состояния S в состояние S*.

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

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

Как правило, язык программирования существует в виде: Стандарта языка — набора спецификаций, определяющих его Как правило, язык программирования существует в виде: Стандарта языка — набора спецификаций, определяющих его синтаксис и семантику; Семантика в программировании — дисциплина, изучающая формализации значений конструкций языков программирования посредством построения их формальных математических моделей.

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

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

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

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

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

Трансляторы делятся на: компиляторы — превращают текст программы в машинный код, который можно сохранить Трансляторы делятся на: компиляторы — превращают текст программы в машинный код, который можно сохранить и после этого использовать уже без компилятора (примером является исполняемые файлы с расширением *. exe). интерпретаторы — превращают часть программы в машинный код, выполняют его и после этого переходят к следующей части. При этом каждый раз при выполнении программы используется интерпретатор.

 Примером языка низкого уровня является ассемблер. Языки низкого уровня ориентированы на конкретный тип Примером языка низкого уровня является ассемблер. Языки низкого уровня ориентированы на конкретный тип процессора и учитывают его особенности, поэтому для переноса программы на ассемблере на другую аппаратную платформу её нужно почти полностью переписать. Определенные различия есть и в синтаксисе программ под разные компиляторы. Правда, центральные процессоры для компьютеров фирм AMD и Intel практически совместимы и отличаются лишь некоторыми специфическими командами. А вот специализированные процессоры для других устройств, например, видеокарт и телефонов содержат существенные различия.

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

 Адресный язык программирования Фортран Алгол Pascal Python Java C Basic C++ Objective C Адресный язык программирования Фортран Алгол Pascal Python Java C Basic C++ Objective C Smalltalk C# Delphi

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

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

Основные соглашения, которые мы используем в псевдокоде: 1)Отступ от левого поля указывает на уровень Основные соглашения, которые мы используем в псевдокоде: 1)Отступ от левого поля указывает на уровень вложенности. Например, тело цикла for (строка 1) состоит из строк 2 8, а тело цикла while (строка 5) содержит строки 6 7, но не 8. Это же правило применимо и для if-then-else. Это делает излишним такие команды типа begin и end для начала и конца блока. В реальных языках программирование такое соглашение используется редко, так как затрудняет чтение программ, переходящих со страницы на страницу.

2) Циклы while, for, repeat и условные конструкции if, then, else имеют тот же 2) Циклы while, for, repeat и условные конструкции if, then, else имеют тот же смысл, что и в Паскале. 3) Символ начинает комментарий идущий до конца строки. 4) Одновременное присваивание i < j < e (переменные i и j получает значение е заменяет два присваивания j < e и i < e 5) Индекс массива пишется в квадратных скобках: А[i] есть i й элемент в массиве А. Знак «. . » выделяет часть массива: А[1. . j] обозначает участок массива А, включающий А[1], А[2], …. A[j].

6) Часто используются объекты (objects), состоящие из нескольких полей (fields), или, как говорят, имеющие 6) Часто используются объекты (objects), состоящие из нескольких полей (fields), или, как говорят, имеющие несколько атрибутов ( attributes). Значение поля записывается как имя_поля[имя_объекта]. Например, длина массива считается его атрибутом и обозначается length, так что длина массива А запишется как length [A]. Переменная, обозначающая массив или объект, считается указателем на составляющие его данные. После присваивания y <- х для любого поля f выполнено f [y] = f [x]. Если мы теперь выполним оператор f [x] < 3, то f [x] = 3 и f [y] = 3, Поскольку после y <- х переменные x и y указывают на один и тот же объект.

7) Параметры передаются по значению (by value): вызванная процедура получает собственную копию параметров. Изменение 7) Параметры передаются по значению (by value): вызванная процедура получает собственную копию параметров. Изменение параметра внутри процедуры снаружи невидимо. При передаче объектов копируется указатель на данные, составляющие этот объект, а сами поля объекта – нет. Например, если х – параметр процедуры, то присваивание y <- х , выполненное внутри процедуры, снаружи заметить нельзя, а присваивание f [x] < 3 можно.

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

Машина Тьюринга Поста – это пример алгоритма. Придуман этот алгоритм независимо друг от друга Машина Тьюринга Поста – это пример алгоритма. Придуман этот алгоритм независимо друг от друга Аланом Тьюрингом и Эмилем Постом.

Машина Тьюринга Поста В состав машины Тьюринга Поста входит неограниченная в обе стороны лента Машина Тьюринга Поста В состав машины Тьюринга Поста входит неограниченная в обе стороны лента , разделённая на ячейки, и управляющее устройство (также называется головкой записичтения(ГЗЧ)), способное находиться в одном из множества состояний. Число возможных состояний управляющего устройства конечно и точно задано. Управляющее устройство может перемещаться влево и вправо по ленте, читать и записывать в ячейки символы некоторого конечного алфавита. Выделяется особый пустой символ, заполняющий все клетки ленты, кроме тех из них (конечного числа), на которых записаны входные данные.

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

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

 Работа машины Тьюринга Поста (T) осуществляется посредством команд, которые выполняет механическое устройство. Команда Работа машины Тьюринга Поста (T) осуществляется посредством команд, которые выполняет механическое устройство. Команда имеет один из следующих стрёх возможных видов: qs ai → qjaj , qs ai → qt. L , qs ai → qj. R L движение головки влево на одну ячейку R – движение головки вправо на одну ячейку

 Смысл команд заключается в том, что : Если головка в состоянии qs обозревает Смысл команд заключается в том, что : Если головка в состоянии qs обозревает ячейку в состоянии ai , то в первом случае она меняет свое состояние на qj , а ячейки на aj , во втором случае – свое состояние на qj и сдвигается влево и, наконец, в третьем – вправо. Конечный набор команд образует программу. Состояние машины – это последовательность состояний ai 1 , …. , ai k ячеек ленты, состояние внутренней памяти qs и номер k воспринимаемой (читаемой) ячейки в состоянии ai k

 Cсостояние машины записываем в виде ai 1 , …. , ai k 1 Cсостояние машины записываем в виде ai 1 , …. , ai k 1 qs ai k …an И называем машинным словом m. Символ qs может быть самым левым, но не может быть самым правым в машинном слове, так как справа от него должно быть считываемое состояние ячейки. Под воздействием программы происходит изменения состояние машины, сопровождающееся переделкой исходного машинного слова m → m(1) → … → m(p)

Сортировка вставками удобна для сортировки коротких последовательностей. Именно таким способом обычно сортируют карты: держа Сортировка вставками удобна для сортировки коротких последовательностей. Именно таким способом обычно сортируют карты: держа в одной руке уже упорядоченные карты и взяв другой рукой очередной карты, мы вставляем ее в нужное место, сравнивая с имеющимися. Запишем алгоритм в виде процедуры Incsertion sort, параметром которой является массив А[1. . n] (последовательность длины n, подлежащая сортировке). Мы обозначаем число элементов в массиве. А через length[A]. Последовательность сортируется на месте, без дополнительной памяти. После выполнения процедуры сортировки массив А упорядочен по возрастанию.

 Индекс j указывает «очередную карту» ( только что взятую со стола). Участок А[1. Индекс j указывает «очередную карту» ( только что взятую со стола). Участок А[1. . j+1] составляют уже отсортированные карты (левая рука), а А[j+1. . n] – еще не просмотренные. В цикле for индекс j пробегает массив слева направо. Мы берём элемент А[j] (строка 2 алгоритма) и сдвигаем идущие перед ним и большие его по величине элементы (начиная c j ) вправо, освобождая место для взятого элемента (строки 4 7). В строке 8 элемент A[j] помещается в освобожденное место.

Типы сложности алгоритмов Сложность задания (описания) объекта. Сложность вычисления (функционирования). Конструктивно энергетическая сложность. Сложность Типы сложности алгоритмов Сложность задания (описания) объекта. Сложность вычисления (функционирования). Конструктивно энергетическая сложность. Сложность задания объекта – это кратчайшая длина программы, наименьшее число команд, которое должно быть введено в идеализированную машину для того, что бы она могла решить любую задачу некоторого класса задач, т. е. предъявить объект, считающийся ее решением. Как правило, в этот класс включают однотипные задачи, поэтому такой класс задач называется массовой задачей.

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

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

 Временем работы (running time) алгоритма мы называем число элементарных шагов, которые он выполняет Временем работы (running time) алгоритма мы называем число элементарных шагов, которые он выполняет — вопрос только в том, что считать элементарным шагом. Мы будем полагать, что одна строка псевдокода требует не более чем фиксированного числа операций (если только это не словесное описание какой то сложной операции — типа «отсортировать все точки по x координате» ). Мы будем различать также вызов (call) процедуры (на который уходит фиксированное число операций) и её исполнение (execution), которое может быть долгим.

 Итак, вернёмся к процедуре Insertion Sort и отметим около каждой строки её стоимость Итак, вернёмся к процедуре Insertion Sort и отметим около каждой строки её стоимость (число операций) и число раз, которое эта строка исполняется. Для каждого j от 2 до n (здесь n = length[A] — размер массива) подсчитаем, сколько раз будет исполнена строка 5, и обозначим это число через tj. (Заметим, что строки внутри цикла выполняются на один раз меньше, чем проверка, поскольку последняя проверка выводит из цикла. )

 Время работы в худшем случае и в лучшем случае сильно различаются. Большей частью Время работы в худшем случае и в лучшем случае сильно различаются. Большей частью нас будет интересовать время работы в худшем случае (worst case running time), которое определяется как максимальное время работы для входов данного размера. o Зная время работы в худшем случае, мы можем гарантировать, что выполнение алгоритма закончится за некоторое время, даже не зная, какой именно вход (данного размера) попадётся.

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

 В некоторых случаях нас будет интересовать также среднее время работы (average case running В некоторых случаях нас будет интересовать также среднее время работы (average case running time, expexted running time) алгоритма на входах данной длины. Конечно, эта величина зависит от выбранного распределения вероятностей (обычно рассматривается равномерное распределение), и на практике реальное распределение входов может оказаться совсем другим. (Иногда его можно преобразовать в равномерное, используя датчик случайных чисел. )

Порядок роста Наш анализ времени работы процедуры INSERTION SORT был основан на нескольких упрощающих Порядок роста Наш анализ времени работы процедуры INSERTION SORT был основан на нескольких упрощающих предположениях. Сначала мы предположили, что время выполнения i й строки постоянно и равно Сi. Затем мы огрубили оценку до ап 2 + bп + с. Допустим, что время работы в худшем случае имеет порядок роста (rate of growth, order of growth) n 2, отбрасывая члены меньших порядков (линейные) и не интересуясь коэффициентом при n 2. Это записывают так: Т(п) = θ(n 2)

 Алгоритм с меньшим порядком роста времени работы обычно предпочтителен: если, скажем, один алгоритм Алгоритм с меньшим порядком роста времени работы обычно предпочтителен: если, скажем, один алгоритм имеет время работы θ(n 2), а другой — θ(n 3), то первый более эффективен (по крайней мере для достаточно длинных входов.

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

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

 Для задачи сортировки эти три этапа выглядят так. Сначала мы разбиваем массив на Для задачи сортировки эти три этапа выглядят так. Сначала мы разбиваем массив на две половины меньшего размера. Затем мы сортируем каждую из половин отдельно. После этого нам остаётся соединить два упорядоченных массива половинного размера в один. Рекурсивное разбиение задачи на меньшие происходит до тех пор, пока размер массива не дойдёт до единицы (любой массив длины 1 можно считать упорядоченным).

 Нетривиальной частью является соединение двух упорядоченных массивов в один. Оно выполняется с помощью Нетривиальной частью является соединение двух упорядоченных массивов в один. Оно выполняется с помощью вспомогательной процедуры MERGE (И, р, q, r). Параметрами этой процедуры являются массив А и числа р, q, r, указывающие границы сливаемых участков. Процедура предполагает, что р ≤ q < r и что участки А[р. . q] и A[q + 1. . r] уже отсортированы, и сливает (merges) их в один участок А[р. . r].

Сортировка слиянием для массива А = (5, 2, 4, 6, 1, 3, 2, 6). Сортировка слиянием для массива А = (5, 2, 4, 6, 1, 3, 2, 6). MERGE-SORT (А, р, г) IF Р < Г THEN Q <— [(Р + R)/2] MERGE-SORT (А, Р, Q) MERGE-SORT (A, Q + 1, R) MERGE (M, P, Q, R) Весь массив теперь можно отсортировать с помощью вызова MERGE-SORT ( А, 1, length[A]). Если длина массива n = length[A] есть степень двойки, то в процессе сортировки произойдёт слияние пар элементов в отсортированные участки длины 2, затем слияние пар таких участков в отсортированные участки длины 4 и так далее до n (на последнем шаге соединяются два отсортированных участка длины n/2).

Анализ алгоритмов типа «разделяй и властвуй» Как оценить время работы рекурсивного алгоритма? При под Анализ алгоритмов типа «разделяй и властвуй» Как оценить время работы рекурсивного алгоритма? При под счёте мы должны учесть время, затрачиваемое на рекурсивные вы зовы, так что получается некоторое рекуррентное соотношение (recurrence equation). Далее следует оценить время работы, исходя из этого соотношения. Вот примерно как это делается. Предположим, что алгоритм разбивает задачу размера n на а подзадач, каждая из которых име ет в раз меньший размер. b Будем считать, что разбиение требует времени D(n), а соединение полученных решений — времени С (n).

Тогда получаем соотношение для времени работы Т(n) на задачах размера n (в худшем случае): Тогда получаем соотношение для времени работы Т(n) на задачах размера n (в худшем случае): Т(n) = а. Т(п/b) + D(n) + С (n). Это соотношение выполнено для достаточно больших n, когда задачу имеет смысл разбивать на подзадачи. Для малых n, когда такое разбиение невозможно или не нужно, применяется какой то прямой метод решения задачи. Поскольку n ограничено, время работы тоже не превосходит некоторой константы.

Анализ сортировки слиянием Для простоты будем предполагать, что размер массива (n) есть степень двойки. Анализ сортировки слиянием Для простоты будем предполагать, что размер массива (n) есть степень двойки. Тогда на каждом шаге сортируемый участок делится на две равные половины. Разбиение на части (вычисление границы) требует времени θ(1), а слияние – θ(n). Получаем соотношение

Анализ сортировки слиянием Это соотношение влечёт Т(n) = θ(n log n), где через log Анализ сортировки слиянием Это соотношение влечёт Т(n) = θ(n log n), где через log мы обозначаем двоичный логарифм (основание логарифмов, впрочем, не играет роли, так как приводит лишь к изменению константы). Поэтому для больших n сортировка слиянием эффективнее сортировки вставками, требующей времени θ(n 2).

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

 В типичном случае динамическое программирование применяется к задачам оптимизации (optimization problems). У такой В типичном случае динамическое программирование применяется к задачам оптимизации (optimization problems). У такой задачи может быть много возможных решений; их «качество» определяется значением какого то параметра, и требуется выбрать оптимальное решение, при котором значение параметра будет минимальным или максимальным (в зависимости от постановки задачи). Вообще говоря, оптимум может достигаться для нескольких разных решений.

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

 Основную часть работы составляют шаги 1 3. Если нас интересует только оптимальное значение Основную часть работы составляют шаги 1 3. Если нас интересует только оптимальное значение параметра, шаг 4 не нужен. Если же шаг 4 необходим, для построения оптимального решения иногда приходится получать и хранить дополнительную информацию в процессе выполнения шага 3. При решении оптимизационной задачи с помощью динамического программирования необходимо сначала описать структуру оптимального решения. Будем говорить, что задача обладает свойством оптимальности для задач (has optimal substructure), если оптимальное решение задачи содержит оптимальные решения её подзадач. Если задача обладает этим свойством, то динамическое программирование может оказаться полезным для её решения

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

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

Категории чисел по Колмогорову В понимание сложности входит числовая характеристика ( длина программы, число Категории чисел по Колмогорову В понимание сложности входит числовая характеристика ( длина программы, число операций и т. д. ). Изучая эти характеристики А. Н. Колмогоров пришел к представлению о наличии четырех категорий чисел: малых, средних, больших и сверхбольших. Число n называют малым, если практический (для человека или машины) возможно перебрать все релейно контактные схемы из n элементов, или равно, выписать для них все соответствующие им булевые функции. Возьмем утверждение – х3 + 1 > 0

 Число n называют средним, если перебрать все схемы невозможно, но можно перебрать сами Число n называют средним, если перебрать все схемы невозможно, но можно перебрать сами элементы или выработать систему обозначений для любой схемы из n элементов. Число n – большое, если невозможен перебор и такого числа элементов, но возможно установить систему обозначений для этих элементов. Если этого сделать нельзя, то число n – сверхбольшое. К малым числам Колмогоров относит, например 3, а к средним 1000. Число видимых звезд на небе – это большое число: их нельзя перебрать, но все они перечислены в звездном каталоге с помощью выработанной системы обозначений.