
- •1.Введение
- •1.1.Декомпозиция и абстракция
- •1.2.Абстракция
- •1.2.1.Абстракция через параметризацию
- •1.2.2.Абстракция через спецификацию
- •1.2.3.Виды абстракций
- •3.Процедурная абстракция
- •3.2.Спецификации
- •3.3.Спецификации процедурных абстракций
- •3.4.Реализация процедур
- •3.5.Более обобщенные процедуры
- •3.6.Создание процедурных абстракций
- •3.7.Заключение
- •4.Абстракции данных
- •4.1.Спецификации для абстракций данных
- •4.2.1.Реализация на языке clu
- •4.2.2.Замечания по поводу операций up и down
- •4.3.Использование абстракций данных
- •4.4.Реализация полиномов
- •4.5.Пояснения для понимания реализаций
- •4.5.1.Функция абстракции
- •4.5.2.Инвариант представления
- •4.6.3.Сохранение инварианта представления
- •4.5.4.Изменяемые представления
- •4.6.Параметризованные абстракции данных
- •4.7.Списки
- •4.8.Упорядоченные списки
3.7.Заключение
В этой главе мы имели дело главным образом с процедурами: что они из себя представляют, как описывается их поведение и как осуществляется их реализация. Мы также рассмотрели два важных преимущества абстракции и необходимость в спецификации.
Абстракция дает два основных преимущества, заключающихся в локальности и модифицируемости. Оба этих преимущества базируются на различии между абстракцией и ее реализациями. Локальность предполагает, что каждая реализация может быть рассмотрена независимо от остальных. Абстракция может быть. использована без уяснения для себя способа ее реализации и реализована без понимания того, как она будет использована. Модифицируемость означает, что одна реализация может быть заменена другой без изменения других программ.
Для достижения этих преимуществ мы должны иметь описание абстракции, которое отлично .от любой ее реализации. До сих пор мы рассматривали спецификацию, которая описывает поведение абстракции на специальном языке спецификаций. Этот язык может быть формальным или неформальным. Пользователи должны опираться на описываемое в спецификации поведение данной процедуры, а создатели процедуры должны обеспечить это поведение. Следовательно, спецификация является соглашением между пользователями процедуры и ее составителями.
Процедуру можно рассматривать как некоторое отображение входных значений в выходные с возможной модификацией некоторых входных значений. Поведение процедуры, подобно другим видам абстракций, описывается в ее спецификации, и здесь мы даем форму неформальных спецификаций процедур. Процедура в языке CLUвводится предложением proc.В других языках она может быть реализована при помощи аналогичного механизма.
Поскольку мы заинтересованы в разработке и реализации хороших абстракций, то заканчиваем главу рассмотрением того, как должны выглядеть процедуры. Желательно наличие таких свойств, как минимальность, простота и обобщенность. Требование минимальности часто ведет к недоопределенным абстракциям. Мы продолжим обсуждение этих свойств в последующих главах по мере рассмотрения других видов абстракций.
Дополнительная литература
Abelson, Harold, and Gerald J. Sussman, with Julie Sussman, 1985. Strac' ture and Interpretation of Computer Programs, chap. 1. Cambrige, Mass.: MIT Press and New York: McGraw-Hill.
Dijkstra, Edgser \V., 1972. Notes on structured programming. In Structured Programming (New York: Academic Press), pp. 1—82.
Wirth, Nikiaus, 1971. Program development by stepwise refinement. Communications of the ACM 14 (4): 221—227. Reprinted in Programming Methodology, А -СЫМюп of Articles Ьц Members of IF IP WG2.3, edited by David Gries (New York: Springer-Verlag), f978.
Упражнения
3.1.Реализуйте
maxt == proc [t: type] (a: array [t]) returns (t) requiresмассив а не пуст и tимеет операцию
gt: proctype (t, t) returns (bool) которая определяет полное упорядочивание по t, effectsВозвращает наибольший элемент в а, определенный через t^gt.
3.2.Определите и напишите процедуру is_ prime,которая определяет, является ля данное целое число простым.
3.3.Обобщите приведенную на рис. 3.3процедуру remove- dupisтак, чтобы она могла работать с массивом произвольного типа. Приведите спецификацию и реализацию.
3.4.Определите процедуру
key.sort = prec [etype: type] (a: ar) ar = array [record Ikeyl, key2: int, elem: etype]]
Процедура key.sortмодифицирует входной массив а, упорядочивая элементы этого массива в возрастающем порядке согласно значениям двух полей ключей. 1\еу1 является первичным ключом. Он используется для предварительной сортировки массива а. Затем в качестве вторичного ключа используется key2.При этом сортируются те элементы, которые имеют то же самое значение keyl(т. е. элементы х и у такие, что x.keyl =у.keyl).Напишите спецификацию и реализацию этой процедуры.
3.5.Спецификация процедуры key.sortможет требовать или не требовать обеспечения условия стабильности сортировки. Сортировка называется стабильной, если все элементы, имеющие одинаковые ключи, сохраняют свои относительные позиции в выходном массиве. Включает ли ваша спецификация из упражнения 4какие-либо положения на этот счет?
3.6.Вам предлагается сделать выбор между двумя процедурами, отыскивающими минимальное значение в массиве из целых чисел. Одна из процедур возвращает наименьшее целее число, если ее аргумент массива пуст. Другая предполагает наличие непустого массива. Какую из процедур вы выберете и почему?
3.7.Предположим, что реализация процедуры сортировки слиянием, показанная на рис, 3.6,была изменена следующим образом: процедура merge осталась без изменений, а процедура merge, sortбыла исключена, так что работа выполнялась непосредственно процедурой sort.Является ли такое изменение хорошей идеей? Какой цели служит процедура merge-sort?Проанализируйте.