Алгоритм 4.4. Сортировка слиянием




ВХОД. Последовательность чисел х1, x2 ,..., хn, где n - степень числа 2.

ВЫХОД. Последовательность чисел у1, y2,..., уn, которая является перестановкой входа и удовлетворяет неравенствам y1 £ y2 £...£ yn.

МЕТОД. Применим процедуру MERGE(S, Т) (merge - слияние), входом которой служат две упорядоченные последовательности S и Т, а выходом - последовательность Q элементов из S и Т, расположенных в порядке неубывания. Поскольку S и Т упорядочены, MERGE требует сравнений не больше, чем сумма длин S и Т без единицы (|S| + |T| -1). Работа этой процедуры состоит в выборе большего из наибольших элементов, остающихся в S и Т, и в последующем удалении выбранного элемента и перезаписи его в Q. В случае совпадения можно отдавать предпочтение последовательности S. Кроме того, применяется процедура SORT(i, j) (см. ниже), сортирующая подпоследовательность xi, xi+1,..., xj в предположении, что она имеет длину 2k для некоторого k ³ 0. Для сортировки исходной последовательности вызывается процедура SORT(1, n).

procedure SORT(i, j)

if i=j then return xi

Else

Begin

m(i+j-1)/2;

return MERGE(SORT(i, m), SORT(m+ 1, j))

End.

 

Подсчёт числа сравнений в алгоритме 4.4 приводит к рекуррентным уравнениям

решением которых по теореме 4.1 является Т (n)= О (nlog2n). Для больших n сбалансированность размеров подзадач даёт значительную выгоду. Аналогичный анализ показывает, что общее время работы процедуры SORT, затрачиваемое не только на сравнение, также есть О (nlog2n).

4.3.4. Динамическое программирование

 

Рекурсивная техника полезна, если задачу можно разбить на подзадачи за разумное время, а суммарный размер подзадач будет небольшим. Из теоремы 4.1вытекает, что если сумма размеров подзадач равна an для некоторой постоянной а >0, то рекурсивный алгоритм, вероятно, имеет полиномиальную временную сложность. Но если очевидное разбиение задачи размера n сводит её к n задачам размера n-1, то рекурсивный алгоритм, вероятно, имеет экспоненциальную сложность.

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

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

Рассмотрим эту технику на примере вычисления произведения k матриц М=М1 x М2 x...x Мk, где Mi - матрица с ri-1 строками и ri столбцами. Порядок, в котором эти матрицы перемножаются, может существенно сказаться на общем числе операций, требуемых для вычисления М, независимо от алгоритма, применяемого для умножения матриц.

Пример 4.1. Будем считать, что умножение (р x q)-матрицы на (q x r)-матрицу требует pqr операций, и рассмотрим произведение (в квадратных скобках указаны размерности матриц).

М= М1 x М2 x М3 x М4

[10 x 20] [20 x 50] [50 x 1] [1 x 100]

Если вычислять М в порядке М1x(М2x(М34)), то потребуется 125000 операций, тогда как вычисления в порядке (М1x(М23))xМ4 занимают лишь 2200 операций.

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

 

Алгоритмы с возвратом

 

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

Далее на примере задачи о ходе коня рассматривается общий принцип разбиения таких задач на подзадачи и использование в них рекурсии.

Задача “Обход конем шахматной доски n x n ”. Конь помещается на поле с начальными координатами Х0, У0. Нужно покрыть ходами коня всю доску (осуществить обход доски) за n 2-1 ход, при том, что каждое поле посещается ровно один раз.

Эта задача покрытия n 2 полей сводится к более простой: или выполнить очередной ход, или установить, что никакой ход невозможен.

Характерная черта этого алгоритма состоит в том, что он предпринимает какие-то шаги по направлению к общему решению, эти шаги фиксируются (записываются), но можно возвращаться обратно и стирать записи, если оказывается, что шаг не приводит к решению, а заводит в “тупик”. Такое действие называется возвратом.

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

procedure try (i)

begin k:= 0; (*инициировать выборку возможных шагов*)

repeat k:= k +1; выбрать k-й возможный путь;

if приемлемо then

begin записать его;

if i < n then (*решение неполно*)

begin try (I +1); (*попробовать очередной шаг*)

if неудачно then стереть запись

End

End

until удачно & (k=m)

End.

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

 

4.4.1. Как разрабатывать алгоритм?

 

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

Однако всегда находились математики (и представители других наук), для которых вопрос: «Как сформировалась идея?» и более общий вопрос: «Как вообще формировать идеи решения или изобретения?» был важнее решения конкретной задачи (проблемы). Многие выдающиеся математики пытались сформулировать принципы и методы решения любой задачи. Среди них первым можно отметить знаменитого греческого математика Паппа, который жил предположительно около 300 г. н. э. В седьмом томе своего "Математического сборника" он говорит об отрасли науки, названной им эвристикой, так (в свободном изложении): "То, что называют эвристикой, можно кратко определить как особое собрание принципов, предназначенное для тех, кто после изучения «Начал» Евклида имеет желание научиться решать математические задачи…".

Эвристика – не совсем чётко очерченная область науки, которая находится на стыке логики, искусственного интеллекта, философии и психологии. Цель эвристики – исследовать методы и правила, как делать открытия и изобретения. Отдельные высказывания о таком исследовании можно уже обнаружить у комментаторов Евклида.

Наиболее известные попытки создать стройную систему эвристики принадлежат Р. Декарту (1596 – 1650) и Г. Лейбницу (1646 – 1716) - двум великим математикам и философам. Первый попытался разработать универсальный метод решения задач, однако его «Правила для направления ума» остались неоконченными. Второй намеревался написать «Искусство изобретения», но не осуществил своего намерения; однако многочисленные отрывки, разбросанные в его трудах, показывают, что у него были интересные мысли по этому вопросу. Он неоднократно подчеркивал значение этого вопроса; так, он писал: «Нет ничего важнее, чем умение найти источник изобретения, – на мой взгляд, это еще интереснее, чем само изобретение».

Б. Больцано (1781 – 1848), логик и математик, оставил интересное и подробное изложение эвристики; он предпослал изложению введение, в котором написал: «… я приложу усилия к тому, чтобы ясно изложить правила и способы исследования, которыми руководствуются все способные люди …».

Следующим в этом ряду назовём Д. Пойа, не столько великого математика, сколько очень талантливого Учителя. Он написал книгу «Как решать задачу?» [14], весьма полезную как учителю, так и ученику не только средней, но и студенту высшей школы (в последнем случае рекомендуем также познакомиться со второй его книгой [15]). По её мотивам написаны книги [2] и [16].

Задача построения алгоритма, как и любая задача, может быть решена в соответствии с методикой, разработанной Д. Пойа [14]. Она заключается в разбиении процесса решения на этапы:

· постановка задачи (понимание постановки задачи);

· составление плана решения (анализ);

· реализация плана (синтез);

· осмысление полученного решения («взгляд назад»)

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



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-08-20 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: