Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методические указания.pdf
Скачиваний:
81
Добавлен:
13.02.2015
Размер:
1.2 Mб
Скачать

1. ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ

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

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

13.1 План разработки алгоритмов и программ

План заключается в следующем:

1.Переформулировать условия задачи.

2.Выяснить, что — на входе и что — на выходе.

3.Составить тестовые примеры (не забыв о крайних случаях).

4.Решить тестовые примеры вручную.

5.Если задача решается как композиция известных задач, то перейти к пункту 9.

6.Разработать алгоритм программы.

7.Выполнить ручную прокрутку.

8.Если есть ошибки, то перейти к пункту 6.

9.Написать текст программы.

Вкачестве примера рассмотрим построение алгоритма решения следующей задачи:

Дана целочисленная таблица А[1:10], требуется подсчитать, сколько раз встречается в ней максимальное по величине число.

Для этого надо последовательно пройтись по всем пунктам плана. 1. Переформулировать условия задачи.

2. Выяснить, что — на входе и что — на выходе.

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

ичто нужно выводить.

Внашем случае новая формулировка: в одномерном массиве посчитать количество максимумов, имея на входе одномерный массив, на выходе — число.

3

3.Составить тестовые примеры (не забыв о крайних случаях).

4.Решить тестовые примеры вручную.

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

Что такое тест? Это те данные, которые вы должны ввести в вашу программу, и то, что вы считаете правильным ответом, который и должна выдать ваша программа в случае ввода этих данных.

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

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

Например, для решаемой задачи достаточно следующих тестов. Если таблица имеет вид:

5 2 4 0 6 11 7 0 2 4,

то максимум 1:11. Если таблица имеет вид: 5 11 4 0 6 11 7 0 2 11,

томаксимумов3. Всеониодинаковыиравны11. Если таблица имеет вид:

5 5 5 5 5 5 5 5 5 5,

товсеееэлементы — максимумыиравны5.

5. Если задача решается как композиция известных задач, то перейти к пункту 9.

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

-поиск максимального элемента в одномерном массиве;

-подсчет числа элементов (в одномерном массиве), равных данному (найденному максимальному).

И тогда можно сразу переходить к 9-му пункту плана, то есть непосредственно к написанию расчетной части программы (листинг 1.1).

Листинг 1.1

max := a[1];

4

for i:=2 to 10 do

if a[i] > max then max:=a[i];

n:=0;

for i:=1 to 10 do

if a[i] = max then inc(n);

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

рассмотрим задачу:

Дана целочисленная таблица А[1:10], надо подсчитать наибольшее число идущих в ней подряд одинаковых элементов.

Для повторения проведем начальные этапы разработки алгоритмов и для этой задачи.

Новая формулировка: в одномерном массиве посчитать наибольшее число идущих подряд одинаковых элементов, имея на входе одномерный массив, а

на выходе — число. Что касается полного множества тестов, то в данном случае оно более сложное:

А= [5 2 4 0 6 11 7 0 2 4] - нет подряд идущих; А= [5 5 5 5 5 5 5 5 5 5] — все подряд идущие;

А= [5 11 4 4 4 11 7 0 2 11] — одна цепочка подряд идущих;

А= [5 11 4 4 4 2 2 2 2 2] — сначала min, потом max; А= [5 4 4 4 4 4 4 2 2 2] — сначала max, потом min.

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

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

Предположим, что вы составили полное множество тестов. Как же теперь составить алгоритм, решающий поставленную задачу?

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

Чтобы помочь формализовать известный вам алгоритм, предлагается использовать следующий мнемонический прием. Представьте, что:

5

-на длинном шоссе разложен миллион рядом лежащих табличек, на которых написаны числа;

-вам требуется решить задачу для этого миллиона чисел;

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

-можно на ладони записывать некоторые числа, чтобы не надо было их помнить;

-сравнивать можно только два числа (оба на ладони, оба на дороге, одно на ладони, другое на дороге);

-нужно придумать схему действий (алгоритм), так чтобы на ладони

появился ответ, когда вы доберетесь до конца шоссе.

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

1.получить правильный ответ (сверив его потом с ответом товарища);

2.придумать схему действий (алгоритм), по которой можно получать правильный ответ всегда (независимо от входных данных).

Попробуем теперь записать алгоритм задачи о подряд идущих элементах для исполнения человеком. Записывать на ладони в этом случае нужно только 2 числа:

-1-е — сколько сейчас одинаковых подряд идущих элементов;

-2-е — максимальное число одинаковых подряд идущих элементов, встреченное до сих пор.

Тогда алгоритм можно написать следующим образом:

Записать на ладони первое число = 1 и второе число = 1. Начиная со второго числа на шоссе и до последнего делать:

если текущее число на шоссе равно предыдущему то увеличиваем на 1 первое число на ладони,

иначе если первое число на ладони больше второго числа на ладони то на место второго числа на ладони записывать первое

(чтобы сохранись максимум подряд идущих) на место первого числа на ладони записать 1

(чтобы начать счет сначала для текущих подряд идущих)

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

6

Соответствующий компьютеризованный алгоритм может выглядеть так:

ввод А[1 10]

1

//разложили числа на шоссе

max =1, tek =

//записали на ладони 2 числа

для i от 2 до

10

//повторяем для чисел от второго до десятого

если A[i] = А[i-1]//если подряд идут

 

то tek = tek + 1 //то инкрементируем текущее

иначе

 

 

//иначе если надо меняем макс

если tek > mах то mах = tek

tek = 1

 

//и начинаем считать сначала

Вывод max

 

//выводим результат

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

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

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

Как же выполнять ручную прокрутку?

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

В качестве тестового примера (назовем его пример 1) выберем массив А с элементами:

5 11 4 4 4 2 2 2 2 2.

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

Итак, ручная прокрутка:

Ввод А [1..10] max = 1, tek = 1

для i от 2 до 10

если А[i] = A[i-1] то tek = tek + 1

7