tema_2,doc

advertisement
Тема 2. Основы структурного проектирования алгоритмов. Файл 308820029
С. 1 из 7
Тема 2. Основы структурного проектирования алгоритмов
1. Сущность структурного программирования. Базовые структуры алгоритмов
2. Язык псевдокод
3. Преобразование и некоторые типовые структуры алгоритмов
Материал к теме: базовые структуры алгоритмов; файлы bas_str1.doc и bas_str2.doc.
В данной теме речь идет о двух принципах структурной методологии: структурном программировании и надъязыковом подходе.
1. Сущность структурного программирования. Базовые структуры алгоритмов
 Принцип структурного программирования состоит в следующем: на любом этапе проектирования алгоритма порядок выполнения действий задается одной из трех конструкций (структур):
 следованием;
 развилкой (ветвлением, альтернативой);
 повторением (циклом).
Суть этих структур хорошо отображается в графической форме средствами языка блок-схем, а в
текстовой – средствами языка псевдокод, детально рассматриваемого в вопросе 2.
При описании базовых структур используется понятие функционального блока. Функциональный
блок – это любая допустимая совокупность действий, рассматриваемая как единое целое и имеющая один вход и один выход. В предельном простейшем случае функциональный блок может
быть представлен одной элементарной операцией изменения данных – вводом, выводом, присваиванием или вызовом процедуры. Ниже функциональные блоки, входящие в состав базовых
конструкций, обозначены S, S1, S2, … Sn.
Следование представляет собой последовательность действий.
S1
S2
Запись на псевдокоде:
…
Sn
S1; S2; … Sn;
Развилка обеспечивает выбор одной из двух альтернатив.
истина
ложь
В
S1
S2
Запись на псевдокоде:
если В то
S1
иначе
S2
кесли;
Если условие B истинно, то выполняется блок S1, иначе – блок S2. Каждый из путей (альтернатива
то, альтернатива иначе) ведет к общей точке слияния, так, что по завершении выполнения конструкции обработка продолжается независимо от того, какой путь был выбран.
Цикл обеспечивает многократное повторение действий.
ложь
В
истина
S
Запись на псевдокоде:
пока В цикл
S
кц;
Действие (блок) S выполняется, пока условие В истинно. Как только условие становится ложным,
цикл завершается. Если до начала выполнения цикла условие ложно, то S не выполнится ни разу.
Приведенный цикл называется цикл-пока.
Тема 2. Основы структурного проектирования алгоритмов. Файл 308820029
С. 2 из 7
Альтернативная форма базовой структуры цикла – цикл-до:
Запись на псевдокоде:
S
цикл
S
до В;
ложь
В
истина
Действие S выполняется до момента, когда условие В станет истинным. В отличие от предыдущей
конструкции, здесь S обязательно выполняется хотя бы один раз.
Эти конструкции преобразуемы одна в другую, и каждая из них может быть выбрана в качестве
базовой. В курсе предпочтение отдается циклу-пока.
 Алгоритм, построенный на основе базовых конструкций, называется структурированным.
 Заметим, что все базовые конструкции имеют один вход и один выход, т.е. являются функциональными блоками.
 Использование ограниченного числа конструкций позволяет по возможности формализовать
процесс построения и анализа алгоритма и получить ясный, легкий для понимания алгоритм. Кроме того, принцип структурного программирования лежит в основе доказательства правильности
(верификации) алгоритмов1.
При структурном подходе анализ данных и управление вычислительным процессом, т.е.операции,
определяющие сложность алгоритма, определяются приведенными конструкциями.
 Является ли перечисленный набор конструкций достаточным для построения любой программы?
Ответ на этот вопрос содержит принцип, называемый «структурной теоремой» и гласящий: всякая
реальная программа может быть построена с использованием трех перечисленных конструкциий:
следования, развилки, повторения. Это и опредеяет их название: базовые управляющие структуры.
Доказательство теоремы состоит в преобразовании алгоритма с произвольной структурой (т.е. с
произвольными переходами между операторами, создающими «блюдо спагетти») в структурированный алгоритм путем формального применения ряда правил. Такой процесс называется
структурированием. Поскольку преобразования применимы к любому алгоритму, теорема полагается доказанной.
Следствие из структурной теоремы: любой неструктурированный алгоритм может быть структурирован.
Замечание. Процесс написания алгоритма с произвольной структурой (по принципу «так быстрее
и проще»), а затем его структурирование дает очень малонаглядный результат, так как распутывание «блюда спагетти» делается за счет введения дополнительных переменных и развилок. Реально гораздо проще и эффективнее сразу проектировать алгоритм как структурированный, т.е.
описывать его средствами базовых структур. Это связано с тем, что по существу базовые конструкции отображают наш способ формального мышления при описании любой деятельности.
 На практике удобно использовать избыточную систему базовых структур, так как существуют целые классы задач, где можно использовать усеченный или модифицированный вариант конструкции, и это упрощает запись. Как правило, в языках проектирования и высокоуровневых языках программирования наличествует три вида развилок и три вида циклов. Полностью базовые структуры,
их описание и кодирование на языках Си и Паскаль приведены в файлах bas_str1.doc и
bas_str2.doc.
Ветвление если-то используется, если действие выполняется только по одной ветви. В таком
случае условие в ветвлении надо записывать так, чтобы действие выполнялось в ветви то.
Например, кн. Лингер Р.,Миллс Х., Уитт Б. Теория и практика структурного программирования. – М.:
Мир, 1982 содержит сильный математический аппарат конструирования и анализа алгоритмов, базирующийся на исчислении предикатов.
1
Тема 2. Основы структурного проектирования алгоритмов. Файл 308820029
С. 3 из 7
Множественный выбор используется, когда некоторое множество действий выполняется в зависимости от значения некоторого ключа, имеющего более двух значений; выбор заменяет последовательность или вложение развилок.
О циклах пока и до сказано выше. На практике могут быть использованы оба, но предпочтительно
не прибегать к двум конструкциям там, где достаточно одной. Цикл-до лучше использовать только
там, где есть уверенность, что он обязательно должен быть выполнен хотя бы один раз и более
наглядно описывает нужные действия.
Цикл-для, или цикл с параметром, используется, когда число повторений цикла известно в алгоритме. В языках программирования он реализован по схеме цикла-пока.
Реализация развилок в языках Паскаль и Си схожа. Что касается циклов, то в Паскале цикл-для
является частным случаем цикла-пока (параметр инициализируется и изменяется с шагом 1 или
-1, а условие состоит в сравнении текущего значения параметра с конечным), а в языке Си этот
цикл, напротив, реализован как самый общий и позволяет в разделах инициализации и коррекции
записывать любые операции, причем более одной в каждом разделе (что может привести к потере
читабельности алгоритма и чего делать не следует).
Следует помнить о специфике синтаксиса развилок и циклов в языках программирования: в ветвях
развилок и в циклах выполняется один оператор, простой или составной. Поэтому при необходимости выполнения в этих конструкциях действий произвольной структуры следует их оформить как
составной оператор (заключить в операторные скобки).
2. Язык псевдокод
 Традиционный способ представления алгоритмов – графический язык блок-схем.
Его достоинством является наглядность. Это важное достоинство, но проявляется оно только при
описании алгоритма на достаточно общем уровне, для выделения общей его структуры и фиксации основных подзадач.
Недостатки языка блок-схем:
 принципиальное отличие от записи программы – блок-схема двумерна, запись программы
линейна;
 отсутствие средств описания данных;
 отсутствие средств описания процедур;
 громоздкость.
Общепринятым языком описания алгоритмов в настоящее время является псевдокод.
 Псевдокод – неполностью формализованный язык, принципиально допускающий словесное
описание алгоритма. С одной стороны, запись алгоритма на псевдокоде близка к естественноязыковой; с другой стороны, конструкции псевдокода достаточно формализованы и представляют собой надъязыковой (обобщенный) вариант описания структур данных и базовых конструкций конкретных языков программирования. Возвращаясь к трехуровневой схеме решения задач с помощью компьютера (тема 1, рис. 1.1), можно сказать, что псевдокод – это средство описания задачи
на логическом уровне.
Использование псевдокода на этапе проектирования – также один из принципов структурной методологии программирования (см. тему 1). Цель такого использования – создание единого нормативного начала в программировании при наличии огромного количества конкретных систем программирования.
 До какой степени должны быть формализованы средства псевдокода? – Это зависит от класса
решаемых задач и используемых средств программирования (т.е. от соотношения абстрактного и
физического уровней постановки и решения задачи).
В любом случае псевдокод должен быть таким, чтобы можно было описать проект решения:
 строго и кратко;
 не теряя смысловой связи с задачей;
 не используя несущественных для описания логики решения деталей конкретного языка
программирования.
Тема 2. Основы структурного проектирования алгоритмов. Файл 308820029
С. 4 из 7
Примером псевдокода, построенного на формальной основе и имеющего строгий синтаксис, является язык PDL (Process Design Language) приведенный в кн. Лингера и др. (см. ссылку на с. 2 темы). Язык не нашел широкого применения из-за его универсальности, приведшей к обратному:
конструкции языка порой настолько близки к конструкциям того же Паскаля, что теряется смысл
их использования как надъязыковых.
Реально эффективнее использовать более свободный синтаксис языка проектирования и формализовать его в зависимости от класса задач.
Например, если речь идет о достаточно сложных алгоритмах обработки достаточно простых данных, то псевдокод должен включать средства описания алгоритма, «очищенные» от особенностей
языка программирования; описание данных может быть приближено к языку программирования.
То же касается структур данных.
При необходимости средства псевдокода можно расширять, вводя новые структуры данных и/или
операции. Так, при работе с записями (record в Паскале) можно ввести в псевдокод соответствующие структуры данных; при работе с динамической памятью можно ввести ряд операций с адресами (например, при проектировании алгоритма на Паскале можно определить операцию увеличения адреса так, как это сделано в Си,; реализацией такой операции будет последовательность
операторов Паскаля).
Таким образом, «псевдокод» – это скорее некоторое условное собирательное название для
средств описания проекта решения задачи, а не жестко определенный единожды язык.
В «классической» части нашего курса акцент делается на проектировании алгоритма, что и определяет используемые средства псевдокода.
По мнению Макконнелла1, значение псевдокода трудно переоценить, поскольку он:
 упрощает пересмотр конструкции алгоритма;
 поддерживает идею итеративного усовершенствования;
 упрощает внесение изменений;
 упрощает комментирование и др.
Помимо прочего, это один из наиболее удобных видов документации, упрощающий сопровождение программного продукта.
 Операторам псевдокода являются:
 элементарные операторы – ввод, вывод, присваивание, вызов процедуры;
 управляющие операторы, т.е. базовые структуры алгоритмов, описанные выше.
Таким образом, псевдокод поддерживает структурный подход. Два принципа методологии – надъязыковой подход и структурное программирование –тесно взаимосвязаны.
 Для записи алгоритмов на псевдокоде будем использовать следующий синтаксис.
алг <имя алгоритма> (<список имен входных и выходных данных>);
арг
Курсивом выделены ключевые слова – фиксиро<описания входных данных>;
ванные последовательности символов с предрез
определенным смыслом.
<описания выходных данных>;
В любое место алгоритма можно вставить комнач
ментарий:
<описания промежуточных данных>;
{<пояснительный текст>}
<операции >
кон;
Операторы псевдокода см. в примере
кон <имя алгоритма>;
Примеры записи алгоритмов наличествуют в лабораторных работах.
 В целях наглядности (при более глубоком рассмотрении – во избежание многих ошибок) запись
алгоритма делается рельефной.
Рельеф для общей структуры алгоритма показан выше. Для отступа оптимальны 2-3 позиции.
1
Макконнелл С. Совершенный код. – СПб, Питер, 2005. – 896 с – с. 212 – 213.
Тема 2. Основы структурного проектирования алгоритмов. Файл 308820029
С. 5 из 7
В теле алгоритма рельеф делается по схеме:
 последовательность операторов записывается на одном уровне с отступом в 2 позиции
от ключевых слов нач и кон;
 в ветвлениях операции в каждой из ветвей смещаются вправо на 2 позиции;
 в циклах операции, выполняемые в цикле, смещаются вправо на 2 позиции.
Пример записи последовательности операторов
np:=0; s:=0.
для i от 1 до n цикл
si:=sqrt(x[i]*x[i]+y[i]*y[i]);
s:=s+si;
если si>r & x[i]>0 & y[i]>0 то
np:=np+1;
кесли;
кц;
p=(np/n)*100;
sa=s/n;
При такой записи значительно снижается вероятность неправильного вложения или завершения
конструкций.
 Код программы также следует записывать с рельефом. Помимо описанного выше, рельеф делается и при записи составного оператора: его содержимое должно быть смещено вправо относительно операторных скобок begin и end. Пример записи приведен ниже.
program points(input,output);{ввод с клавиатуры, вывод на экран}
uses crt; {подключение модуля для работы с экраном}
const
nmax=100; {верхняя граница массива}
var
n,i:integer;
r,p,sa:real;
x,y:array[1..nmax] of real;
begin
{A0.1 - ввод-вывод входных данных}
............
{A0.2. Обработка}
{А0.2 - обработка}
np:=0; s:=0;
for i := 1 to n do
begin
si:=sqrt(x[i]*x[i]+y[i]*y[i]);
s:=s+si;
if (si>r) and (x[i]>0) and (y[i]>0) then
np:=np+1;
end;
p=(real(np)/n)*100;
sa=s/n;
{A0.3 - вывод результатов}
writeln(' Искомый процент точек = ',p:4:1); {p по обр9}
writeln(' Среднее удаление = ',sa:4:1); {sa по обр9}
end.
 Для описания и вызова процедур на псевдокоде будем использовать синтаксис, аналогичный
синтаксису описания алгоритма
Тема 2. Основы структурного проектирования алгоритмов. Файл 308820029
С. 6 из 7
•• Процедура общего вида (подпрограмма)
Описание
{назначение процедуры}
проц <имя процедуры>(<список формальных параметров>);
арг <список описаний входных параметров>;
рез <список описаний выходных параметров>;
нач <список описаний локальных переменных>;
<операторы>
кон;
кон <имя процедуры>;
Вызов (обращение) записывается как отдельный оператор в вызывающем алгоритме:
<имя процедуры>(<список фактических параметров>);
•• Функция
Описание
<тип>функ<имя функции>(<список входных форм. параметров>);
арг <список описаний входных параметров>;
нач <список описаний локальных переменных>;
<операторы вычисления результирующего значения>
<имя функции>:=<значение>;
кон;
кон <имя функции>;
Единственное выходное значение присваивается имени функции. Во избежание неконтролируемых ошибок целесообразно делать это присваивание только один раз и соответствующий оператор записывать последним из операторов обработки.
Вызов (обращение) осуществляется через указатель функции – конструкцию следующего вида:
<имя функции>(<список фактических параметров>)
Поскольку алгоритм на псевдокоде – это текст проекта, не обрабатываемый компилятором, процедуры можно описывать и размещать независимо от вызывающего алгоритма и отдельно от него
(на отдельных листах и/или в отдельных файлах).
Код процедуры должен быть размещен в соответствии с правилами языка программирования. При
работе в среде Паскаля (turbo или borland) процедуры размещаются в разделе процедур программы program(внутренние процедуры) или в отдельном модуле unit. При работе в среде Delphi процедуры размещаются в разделе процедур модуля формы (внутренние процедуры) или в отдельном модуле unit.
3. Преобразование и некоторые типовые структуры алгоритмов
 Итак, в схемах базовых структур S , S1, S2, … Sn – функциональные блоки; сами базовые структуры также являют собой функциональные блоки. Таким образом, внутри любой из структур в качестве S , S1, S2, … Sn может выступать любая структура этого же набора.
В таком случае справедливы преобразования «структура – функциональный блок»:
пока В цикл
S
кц;
если В то
S1
иначе
S2
кесли;
S1
S
и т.д.
Тема 2. Основы структурного проектирования алгоритмов. Файл 308820029
С. 7 из 7
Преобразование
– укрупнение алгоритма. Используется для понимания алгоритма, когда
нас не интересуют детали, и доказательства его правильности.
Преобразование
– детализация. Используется в процессе проектирования алгоритма по
нисходящей схеме, т.е. исходя из единого функционального блока, соответствующего задаче в
целом, который постепенно раскрывается в сложную структуру. При этом алгоритм остается
структурированным на любом уровне детализации.
 Некоторые типовые структуры алгоритмов
 В конструкции цикла S – ветвление: цикл с разветвлением
пока B цикл
если B1 то
S1
S иначе
S2
кесли
кц;
 В конструкции цикла S – цикл: вложенные (кратные) циклы
пока B1 цикл
пока B2 цикл
S
S1
кц;
кц;
Таким образом, раскрывая функциональный блок в какой-либо базовой конструкции также как базовую конструкцию, можно получить сколь угодно сложные алгоритмы, сохраняющие структурированность.
Download