
- •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.4.Реализация процедур
Реализация процедуры должна выполнять действия, определенные в спецификации. В частности, она должна модифициро-' вать только те входные параметры, которые указаны в предложенииmodifies, а условия в предложенииrequiresдолжны выполняться для всех входных значений. Выходные значения должны соответствовать требованиям, указанным в предложенииeffects.
Каждый язык программирования имеет свой механизм реализации процедурных абстракций. В языке CLUэти абстракции реализуются при помощи процедур CLU,обозначаемых сокращенноproc.
На рис. 3.4показаны две процедуры, написанные на языкеCLUи реализующие функциюsearch. Одна из них использует линейный поис-к, а вторая —бинарный. Эти две реализации во многом отличаются друг от друга. Например, для всех небольших массивов бинарный поиск быстрее линейного. Кроме этого, если элемент х встречается в массиве а более одного раза, то две процедуры могут -возвратить в качестве результата различные значения индексов. Наконец, если х содержится в массиве а, но сам массив при этом не отсортирован, то процедура, использующая алгоритм бинарного поиска, может возвратитьhigh(а) + + 1,а другая процедура может отыскать требуемый элемент х (рассмотрим, например, массив а = [1:1, 7, 6, 4, 9)и х == 7). Тем не менее обе процедуры являются корректными реализациями абстракцииsearch, поскольку обе они выполняются согласно указанной для них спецификации.
ai = array (int] % аббревиатура search = proc (a: ai, х: iiit) returns (int) % реализация с использованием линейного поиска i: int := ai$low (а) while i (= ai$high (a) do if a [i ] == х then return (i) end
if a [i] == x then i :== i 4- I else return (ai$high (a) + 1) end end % конец цикла while return (i) end search
search = proc (a: ai, х: int) returns (int) % реализация с использованием бинарного дерева low: int :== ai$iow (a) high: int := ai$high (a) while (low (= high) do mid: int :== (low+ high)/2 val: int := a [mid] if x (val then high := mid — I else if x = val then return (mid) else low := mid + I end end
return (ai$high (a) + 1) end search
Рис. 3.4.Две реализации процедурыsearch.
В приводимом примере для облегчения прочтения и понимания программы мы придерживались ряда соглашений. Во-первых, мы использовали для формальных параметров те же имена, что и в спецификации. Это соглашение помогает связать реализацию абстракции со спецификацией. За заголовком мы поместили комментарий, поясняющий работу алгоритма. Наконец, мы придерживались общепринятых правил форматирования.
sort = proc (a: array [int]) returns (b: array [int])
effectsВозвращает новый массив с теми же границами, что и а, и содержащий элементы из массива а, упорядоченные по возрастанию.merge_sort==proc (a: array [int I, low, high: int) returns (array [int])
requires low (a) ^ low <. high ^ high (a).
effectsВозвращает новый массив с нижней границей, как и у массива а, и содержащий элементы массиваa[low],...,a[high], расположенные в возрастающем порядке.
merge == proc (a, b: array [int]) returns (array [int]) requires Массивы а и b упорядочены по возрастанию.
effectsВозвращает новый массив с тем же значением для нижне.й Гранины, что и у массива а, и содержащий элементы массивов а и b,расположенные в возрастающем порядке.
Рис, 3.5.Специ^икапия дляmergesort.
ai == array [int] sort = proc (a: ai) returns (ai) % сортировка методом «сортировка слиянием»
if ai$empty (a) then
%создание пустого массива с нижней границейlow(а)
return (ai$create (ai$low (a)) end
return (merge.sort (a, ai$low (a), ai$high (a))) end sort
merge_sort == proc (a: ai, low, high: int) returns (ai) if low < high
then % сортировка двух половин и слияние результата mid: int :== (low + high)/2 return (merge (merge_sort (a, low, mid),
merge_sort(a,mid+I,high)))else %массив а уже отсортирован, однако мы должны
% возвратить новый массив b: ai := ai$create (low) ai$addh (b, a [low]) return (b) end end merge _sort inerge = proc /a, b: ai) returns (ai) alow: int := ai$low (a) bJow: int := ai$low (b) a_high: int := ai$low (a) b.high: int :== ai$low (b) c: ai :== ai$create (alow) % слить а и b
while alow (== aJligh cor bJow (= b_high do if alow) aJligh cor (bJow (= b_high cand b [bJow] (a [alow]) then % переслать элемент из b либо потому, что все элементы из а % уже переслали, либо потому, что следующий элемент из b % меньше, чем следующий элемент из а ai$<iddii (с, b [bJow]) bJow :== bJow+ I
Процедурная абстракция
начать с нижней грани !.ей, равнойalow
elseend
%переслать элемент из массива а
ai$addh (с, а [alow]) alow :== alow -[- 1
end %конец циклаwhile
return(с)
endmerge
Рис. 3.6.Реализация метода сортировки слиянием.
В качестве второго примера рассмотрим сортировку массива.. Одним из возможных способов является метод сортировки слиянием, который сводит задачу к слиянию двух уже отсортированных массивов. Мы начинаем с деления массива на две части, затем сортируем каждую из них и объединяем результаты:%сортировка первой половины массива%сортировка второй половины массива%объединение двух отсортированных частей. Для выполнения этих шагов используем две дополнительные процедуры: процедуруmergeдля операции слияния и процедуруmerge_sortдля сортировки каждой части массива. Процедураmerge_sortвыполнит эти же три шага для частей массива, реализуя рекурсивный алгоритм.
На рис. 3.5показаны спецификации для процедурыsortи двух вспомогательных абстракций. Отметим, что процедураsortне модифицирует входной массив, а процедурыmergeи merge_sort являются частичными. На рис. 3.6приведены процедурыCLU, реализующие данные абстракции.