
- •6. Абстракции данных
- •6.1 Представление рациональных чисел
- •6.1.1 Первое внутреннее представление рациональных чисел
- •6.1.2 Второе внутреннее представление рациональных чисел
- •6.1.3 Функциональный тип данных
- •6.1.4 Третье внутреннее представление рациональных чисел
- •6.2 Представления множеств
- •6.2.1 Функции над множествами. Определения
- •6.2.2 Представление множеств списками
- •6.2.2.1 Неупорядоченные множества
- •6.2.2.2 Упорядоченные множества
- •6.2.3 Представление множеств двоичными деревьями
- •6.2.4 Представление древовидных структур
6.1.1 Первое внутреннее представление рациональных чисел
У нас есть неразлучная пара функций – car и cdr и такая же неразлучная связка числтель-знаменатель и поэтому ничего не стоит определить основные функции построения рациональных чисел самым естественным способом.
>(define (make-rat n d) (cons n d))
>(define (числитель r) (car r))
>(define (знаменатель r) (cdr r))
Попробуем, что получилось на таком примере:
> (define r1 (make-rat 1 2))
> (define r2 (make-rat 1 3))
> (define r3 (add-rat r1 r2))
> r3
(5 . 6)
>
(display-rat (sub-rat r3 r2)) ====
=9/18
> (display-rat r1)
=1/2
Итак, идея абстракции данных воплотилась у нас в три структурных модуля:
Программы, использующие рациональные числа |
add-rat mul-rat div-rat eq-rat |
Обращение к рациональным числам |
make-rat числитель знаменатель |
Представление рациональных чисел как пар |
сons сar cdr |
Надо заметить, что развитие или изменение каждого из них – явления независимые. Подробности того, как реализованы объекты каждого уровня, несущественны для остальной части системы.
К примеру, программы, непосредственно использующие рациональные числа, манипулируют исключительно в терминах функций «общего пользования» рациональных чисел: (add-rat,mul-rat...) и ничем другим.
Идея абстракции данных даёт следующее:
Во-первых, она помогает разбить большую систему на меньшие части, которые могут разрабатываться независимо.
Во-вторых, значительно облегчается процесс написания и корректирования программы.
Любая сложная структура данных может быть представлена всякими способами, но выбор представления данных будет влиять только на программы, работающие с этими данными и, таким образом, если представление в дальнейшем будет изменено, соответственно придется изменять и программы, но связанные только с этим представлением.
Итак, у нас потихоньку выкристаллизовалось понятие интерфейсных функции, т.е. таких функций, которые выступают в качестве своеобразного «барьера абстракции» разделяющего различные «уровни» системы.
6.1.2 Второе внутреннее представление рациональных чисел
Возвратимся к нашей программе рациональных чисел.
Заметьте, что нас совершенно не интересует, как пары реализованы внутренне, потому что мы оперируем ими исключительно в терминах функций cons, car, и cdr.
Предположим, чтобы избежать возможного роста чисел, образующих дроби, мы решили представлять числа в сокращённой форме. Всё, что для этого потребуется – изменить функцию конструктор рациональных чисел.
Вспомнив о функции gcd (НОД - Наибольшем Общем Делителе), перепишем составляющие пары так: числитель n заменим на n/gcd(n,d) а знаменатель d d/gcd(n,d), получаем новое представление:
> (define (make-rat n m)
(let ((g (gcd n m)))
(cons (/ n g) (/ m g))) )
Числитель и знаменатель – остаются прежними.
> (define r1 (make-rat 1 2))
> (define r2 (make-rat 1 3))
> (define r3 (add-rat r1 r2))
> r3
(5 . 6)
> (display-rat (sub-rat r3 r2)) ; происходит еще и сокращение числа
=1/2
> (display-rat r1)
=1/2