Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
48
Добавлен:
23.03.2015
Размер:
396 Кб
Скачать
☆

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. Специ^икапия для merge sort. 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) aJow: 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 (aJow) % слить а и b

while aJow (== aJligh cor bJow (= b_high do if aJow) aJligh cor (bJow (= b_high cand b [bJow] (a [aJow]) then % переслать элемент из b либо потому, что все элементы из а % уже переслали, либо потому, что следующий элемент из b % меньше, чем следующий элемент из а ai$<iddii (с, b [bJow]) bJow :== bJow+ I

Процедурная абстракция

начать с нижней грани !.ей, равной aJow

else end

% переслать элемент из массива а ai$addh (с, а [aJow]) aJow :== aJow -[- 1

end % конец цикла while return (с) cp.d пиг^е Рис. 3.6. Реализация метода сортировки слиянием.

ментарий, поясняющий работу алгоритма. Наконец, мы придер­живались общепринятых правил форматирования.

В качестве второго примера рассмотрим сортировку массива.. Одним из возможных способов является метод сортировки слия­нием, который сводит задачу к слиянию двух уже отсортирован­ных массивов. Мы начинаем с деления массива на две части, за­тем сортируем каждую из них и объединяем результаты: % сортировка первой половины массива % сортировка второй половины массива % объединение двух отсортированных частей Для выполнения этих шагов используем две дополнительные про­цедуры: процедуру merge для операции слияния и процедуру merge_sort для сортировки каждой части массива. Процедура merge_sort выполнит эти же три шага для частей массива, реали­зуя рекурсивный алгоритм.

На рис. 3.5 показаны спецификации для процедуры sort и двух вспомогательных абстракций. Отметим, что процедура sort не модифицирует входной массив, а процедуры merge и merge_sort являются частичными. На рис. 3.6 приведены процедуры CLU, реализующие данные абстракции.

Соседние файлы в папке POSIBNIK