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

2.2. Динамическое распределение памяти

Такое рекурсивное описание вполне корректно с точки зрения синтаксических правил языка Паскаль. Но никакая хитроумная программа не смогла бы работать с данными такой структуры. Причиной этого является противоречие между статическим описанием данных и динамической природой этих данных. Рассмотрим этот вопрос подробнее.

Язык Паскаль требует описания всех переменных, используемых в программе. Компилятор, анализируя текст Паскаль-программы, распределяет память под все описанные данные, до начала выполнения программы, сохраняя это распределение до завершения программы. Причем каждая переменная структурного типа размещается в памяти целостным куском, условный адрес которого определяется именем этой переменной. Такое распределение памяти называется статическим. В нашем примере структуру такого участка памяти условно можно изобразить в следующем виде:

op

true id

false ?

Знак "?" отражает неопределенную ситуацию для компилятора, вызванную рекурсией. Рекурсия возникает, если t = false. В этом случае объем требуемой памяти будет зависеть от конкретного обрабатываемого выражения, а это станет известно только при вводе этих данных. Другими словами, объем памяти определяется динамически, при выполнении программы.

Ниже приведены схемы распределения памяти для примеров 1-3.

1) x + y 2) (x / (y+z)) * w

op

true x

false y

*

/

true x

+

false false true y

false x

true w

3) x * (y + z)

*

true x

+

false true y

false z

На этих схемах ясно виден результат рекурсивного процесса: в области памяти фиксированного объема, обозначенной знаком "?" может разместиться простая переменная (пример 1), или вся структура (пример 2), для которой рекурсивный

процесс может повториться и мы получим следующий уровень рекурсии (пример 3). Количество таких повторений не определено заранее: то есть до конца ввода всего выражения. Такой способ распределения памяти можно сравнить с заполнением газом воздушного шара. Но так же, как шар нельзя надуть, поместив его, например, в спичечный коробок, так и динамическую структурную переменную невозможно распределить в статическую память "жесткого" объема. Другими словами, для рекурсивных структур невозможно определить фиксированный размер памяти и компилятор не может приписать компонентам такой структуры определенные адреса.

Итак, со стороны синтаксиса языка Паскаль нет никаких нарушений при описании рекурсивных типов данных. Предупреждает возможные ошибки "правило опережающего описания" языка Паскаль: прежде чем объект используется, его надо описать. В нашем примере в описании типа expression упоминается тип term, который описан дальше. Поэтому при компиляции этого фрагмента программы возникнет ошибка.

Для решения проблемы динамического распределения памяти, в частности под рекурсивный тип данных, используется ссылочный способ реализации данных.

Рекурсивная переменная не должна представлять целостную структуру в памяти, а каждый элемент структуры выделен отдельно и занимает отдельную область в любом свободном месте памяти. Связь между элементами устанавливается неявно, в виде адресных ссылок (указателей) на области памяти. Переменная ^term является ссылкой на область памяти, где размещена структура term, точно также ^expression ссылается на структуру expression.

Указателей описываются как статические переменные, но адреса им выделяются только при выполнении программы, т.е. память заполняется динамически.

TYPE

expression = record

op : operator;

opd1,opd2 : ^term

end;

term = record

case t: Boolean of

true: (id: alfa);

false: (subex: ^expression)

end;

Пример 2. Генеалогическое дерево состоит из имени человека и двух генеалогических деревьев его родителей. Такое рекурсивное определение неизбежно приводит к бесконечной структуре. Реальные генеалогические структуры конечны, потому что на каком-то уровне сведения о предках отсутствуют. Если мы используем для описания рекурсивную структуру, то она будет иметь следующий вид:

true Ted

true Fred

true Adam

false

false

false

true Mary

false

true Eva

false

false

(2)

type ped = record

case t: Boolean of

true: (name: alfa;

father, mother: ped)

false: ()

end;

Для конкретного примера структура

г

енеалогического дерева может быть изо-

б

ражена 2 способами:

Ted

Fred Mary (1)

 Adam Eva

У

пражнение. Изобразите двумя способами

структуру своего генеалогического дерева.

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