Современная электронная библиотека ModernLib.Net

Программирование на языке пролог

ModernLib.Net / Программирование / Клоксин У. / Программирование на языке пролог - Чтение (стр. 4)
Автор: Клоксин У.
Жанр: Программирование

 

 


Наконец, рассмотрим свойство ассоциативностиоператоров. Необходимость знания этого свойства становится очевидной, когда нам требуется определить порядок выполнения операторов с одинаковым приоритетом. Например, какому выражению эквивалентно выражение «8/2/2» – «(8/2)/2» или «8/(2/2)»? В первом случае при интерпретации выражения было бы получено значение 2, во втором 8. Для того чтобы иметь возможность разделить эти два случая, необходимо знать, является ли данный оператор левоассоциативнымили правоассоциативным. Левоассоциативныйоператор должен иметь слева операции одинаковогоили низшегоприоритета, а справа – операции низшегоприоритета. Например, все арифметические операции (сложить, вычесть, умножить и поделить) являются левоассоциативными. Это означает, что выражения, подобные «8/4/4», интерпретируются как «(8/4)/4», а выражение «5+8/2/2» эквивалентно «5+((8/2)/2)».

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

Напомним, что структура, образованная арифметическими операторами, подобна любой другой структуре. На самом деле никакие арифметические действия не выполняются до тех пор, пока не встретится предикат 'is'(есть), описанный в разд. 2.5.

2.4. Равенство и установление соответствия

В Прологе существует особый предикат равенство,являющийся инфиксным оператором, обозначаемым литерой '='. Когда делается попытка доказать согласованность с базой данных целевого утверждения


?- X = Y.


(произносится X равно Y),Пролог пытается установить соответствиемежду Xи Y; целевое утверждение «доказуемо», если такое соответствие имеется. Это действие можно представить себе как попытку сделать X и Y равными.Предикат равенства является встроенным,т. е. он уже определен в Пролог-системе. Предикат равенства работает так, словно определен следующий факт: X = X.

Внутри всякого утверждения Xвсегда равно X, и это свойство использовано нами при определении предиката равенства.

При согласовании с базой данных цели вида X = Y, где Xи Y– любые термы, в которых могут содержаться неконкретизированные переменные, действуют следующие правила:

• если Xпредставляет собой неконкретизированную переменную, а переменная Yконкретизирована (какое именно значение ей дано, неважно), то Xи Yравны. Кроме того, Xстанет конкретизированной – ей будет дано то же значение, что и Y. Например, следующий вопрос приведет к тому, что Xбудет присвоено значение в виде структуры: ехать(клерк, велосипед):


?- ехать(клерк, велосипед) = X.


• целые числа и атомы всегда равны самим себе. Например, попытки согласовать следующие целевые утверждения дадут результаты, показанные справа:


полицейский = полицейский /* верно */

бумага = карандаш /* ложно */

1066=1066 /* верно */

1206=1583 /* ложно */


• Две структуры равны, если они имеют один и тот же функтор и одинаковое число аргументов, причем все соответствующие аргументы равны. Например, при согласовании следующего целевого утверждения Xбудет присвоено конкретное значение велосипед:


ехать(клерк,велосипед) = ехать(клерк,Х).


Структуры могут быть вложены одна в другую на любую глубину. Если такие вложенные структуры проверяются на равенство, проверка займет больше времени, поскольку необходимо проверить все структуры. Попытка согласовать следующую цель:


a(b,C,d(e,F,g(h,i,J)))=a(B,c,d(E,f,g(H,i,j))).


будет успешной, апеременные В, С, F, Е, Jбудут конкретизированы, им будут присвоены соответственно значения b, с, f, e, j. Что произойдет, если мы попытаемся приравнять две неконкретизированные переменные? Это специальный случай первого из вышеприведенных правил. Так, цель будет согласована и две переменные станут сцепленными.Если две переменные сцеплены, то при конкретизации одной из них второй переменной будет автоматически присвоено то же самое конкретное значение, что и первой. Таким образом, в следующем правиле второй аргумент будет конкретизирован так же, как первый:


ничего_не_делать(Х,Y):- Х = Y.


Целевое утверждение X=Y всегда верно (т. е. согласуется с базой данных), если один из аргументов неконкретизирован. Более простой способ записи такого правила заключается в использовании того факта, что переменная равна самой себе:


ничего_не_делать(Х,Х).


Пролог предоставляет также предикат '\=' соответствующий не равно.Целевое утверждение Х\=Yверно в тех случаях, когда не доказуемо утверждение X=Y, и наоборот. Таким образом, Х\=Yозначает, что X не может быть сделано равным Y.

Упражнение 2.1.Скажите, верны ли следующие целевые утверждения, какие переменные будут конкретизированы и какие им будут даны значения:

пилоты(А, Лондон) = пилоты(лондон, париж)

точка(Х,Y,Z) = точка(Х1,Y1,Z1) = слово(буква)

существительное(альфа) = альфа

'викарий' = викарий

f(X,X) = f(a,b)

f(X,a(b,c)) = f(Z,a(Z,c)

2.5. Арифметика

ЭВМ часто используют для выполнения действий над числами. С помощью арифметических операций можно сравнивать числа и проводить вычисления. В данном разделе будут приведены примеры такого использования арифметических операций.

Рассмотрим сначала сравнение чисел. Для двух заданных чисел всегда можно сказать, равно лиодно число другому, меньше лиодно число другого, больше лиодно число другого. Пролог предоставляет некоторые «встроенные» предикаты, позволяющие

сравнивать числа. Для этого могут использоваться обсуждавшиеся в разд. 2.4 предикаты '='и '\='. Их аргументами могут быть конкретизированные переменные, значениями которых являются целые числа, а также целые числа, записанные в виде констант. Существует еще несколько предикатов, позволяющих сравнивать числа. Перечислим здесь все эти предикаты, отметив предварительно, что каждый из них можно использовать в форме инфиксного оператора.

X = Y X и Y представляют одно и то же число

X \= Y X и Y представляют разные числа

X ‹ Y X меньше Y

X › Y X больше Y

X =‹ Y X меньше или равно Y

X ›= Y X больше или равно Y

Отметим, что символ «меньше или равно» записывается не так, как во многих других языках программирования (обычно ‹=). Это сделано в Прологе для того, чтобы программист мог использовать похожий на стрелку атом ‹= для своих собственных нужд.

Поскольку операторы сравнения являются предикатами, можно было бы предположить, что в Прологе допустим следующий факт:


2›3.


утверждающий, что 2 на самом деле больше 3. Факты, подобные этому, с формальной стороны полностью соответствует правилам Пролога. Однако Пролог не разрешает добавлять факты к «встроенным» предикатам. Такая особенность предотвращает непредсказуемые изменения смысла встроенных предикатов. В главе 6 будут описаны все встроенные предикаты, в том числе и те, с которыми мы уже познакомились.

В качестве первого примера использования чисел предположим, что у нас есть база данных, содержащая сведения о принцах, правивших Уэльсом в 9-м и 10-м веках. Предикат правил(Х,Y,Z)истинен, если принц с именем Xнаходился у власти с года Yпо год Z. Список фактов базы данных выглядит следующим образом:


правил(родри,844,878).

правил(анаравд,878,916).

правил(хивел_дда,916,950).

правил(лаго_ад_идвал,950,979).

правил(хивел_аб_иеуаф,979,985).

правил(кадваллон,985,986).

правил(маредудд, 986,999).


Теперь предположим, что мы хотим узнать, кто был на троне Уэльса в каком-то конкретном году. Можно было бы определить правило, аргументами которого являлись бы имя и дата и которое просматривало бы базу данных и сравнивало заданную дату с теми, что указаны в фактах. Давайте определим предикат принц(X, Y),который истинен, если принц по имени Xбыл на троне в год Y:

X был

  принцем в год Y, если:

 X правил с года А по год В и

 Y находится между А и В или совпадает с А или В.

Первое целевое утверждение будет согласовываться с базой данных путем поиска подходящего факта. Второе целевое утверждение верно, если Yравно А, или Yравно В, или Yлежит между Аи В. Для проверки можно использовать утверждения Y›=Аи Y=‹В. Переписав это на Прологе, получаем следующее правило:


принц (X,Y):-правил(Х,А,В),Y ›= А,Y =‹ В.


Ниже приведено несколько возможных запросов и ответов, даваемых Пролог-системой.


?- принц(кадваллон,986).

да

?- принц(родри,1979).

нет

?- принц(Х,900).

Х = анаравд

да

?- принц(X,979).

X = лаго_ад_идвал ;

X = хивел_аб_иеуаф да


Заметьте использование переменных в последних примерах. Убедитесь, что вы понимаете, как работает механизм поиска Пролога при ответе на подобные вопросы.

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

Рассмотрим следующую базу данных, содержащую сведения о населении и площади некоторых стран в 1976 г. Для представления связи между страной и ее населением будет использоваться предикат нас.В наши дни население обычно характеризуется довольно большими числами. Не все версии Пролога позволяют работать с такими числами. Поэтому будем исчислять население в миллионах: нас(Х, Y)означает, что население страны Xсоставляет примерно « Yмиллионов» людей. Предикат площадьбудет обозначать связь между страной и ее площадью (в миллионах квадратных километров):


нас(сша,203).

нас(индия, 548).

нас(китай,800).

нас(бразилия,108).

площадь(сша,8).

площадь(индия,3).

площадь(китай,9).

площадь(бразилия,8).


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

Введем предикат плотность(Х,Y), где X – это страна, a Y – плотность населения в данной стране, и запишем соответствующее правило на Прологе:


плотность(X,Y):-нас(Х,Р), площадь(Х,А), Y is Р/А.


Данное правило читается следующим образом:

Плотность населения страны X представляется числом Y, если:

 Население X- это Р, и Площадь X- это A, и Y вычисляется делением Р на A.

В правиле используется оператор деления '/' введенный в предыдущем разделе. Операция деления выполняется на самом деле как целочисленное деление, сохраняющее только целую часть результата.

Новым здесь является инфиксный оператор 'is'. Его правый аргумент – терм, интерпретируемый как арифметическое выражение. Для того чтобы выполнить 'is', Пролог сначала вычисляет его правый аргумент в соответствии с правилами арифметики. Результат вычислений проверяется на соответствие с левыми аргументами, чтобы определить, доказуемо ли целевое утверждение. В вышеприведенном примере переменная Yдо исполнения isне конкретизирована, и она остается в таком состоянии до вычисления выражения. Когда выражение вычислено, Yпринимает значение, равное полученной величине. Это означает, что должны быть известны значения всех переменных, находящихся справа от is.

Предикат isнужно использовать каждый раз, когда требуется вычислить арифметическое выражение. Напомним, что конструкции вида Р/Аявляются такими же обычными структурами Пролога, как и автор(эмили,бронте).Но если некоторая структура интерпретируется как арифметическое выражение, то к ней применяется специальная операция, заключающаяся в фактическом выполнении арифметических действий над двоичными представлениями элементов структуры и получении соответствующего результата. Эта операция называется вычислениемарифметического выражения. Не любую структуру можно вычислить как арифметическое выражение. Например, очевидно, что нельзя вычислить структуру автор,поскольку функтор авторне определен как арифметическая операция.

Вернемся к примеру со средней плотностью населения. Нетрудно видеть, что типичные вопросы и ответы на них выглядят следующим образом:


?- плотность(китай,X).

X=89

?= плотность(турция,X).

нет


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

Набор допустимых арифметических операций зависит от используемой ЭВМ. Однако все Пролог-системы обеспечивают выполнение следующих операций:

X+Y сумма X и Y

X–Y разность X и Y

X*Y произведение X и Y

X/Y частное от деления X на Y

X mod Y остаток от деления X на Y

Этот список вместе со списком операторов сравнения, приведенным выше, содержит все, что необходимо для решения простых арифметических задач. Поскольку Пролог в основном ориентирован на нечисловые задачи, арифметические возможности не так важны, как в других языках программирования.

2.6. Общая схема согласования целевых утверждений

Для ответа на вопрос, поступивший от программиста, Пролог выполняет решение некоторой задачи. Вопрос содержит конъюнкциюцелевых утверждений, которые необходимо попытаться доказать, т. е. проверить на согласованность с базой данных. Для доказательства целевых утверждений Пролог использует известные утверждения.Факт может привести к немедленному доказательству (согласованию) целевого утверждения, в то время как правило может только свести данную задачу к конъюнкции предикатов-подцелей. Однако использование некоторого утверждения возможно только, когда оно «подходит» к рассматриваемому целевому утверждению, т. е. соответствует ему (сопоставимо с ним). Если целевое утверждение не доказано, возбуждается процесс возврата.Процесс возврата заключается в пересмотре проделанной работы и попытках передоказать (вновь согласовать) целевые утверждения путем поиска альтернативных путей доказательства. Более того, если программист неудовлетворен ответом на свой вопрос, он может сам инициировать процесс возврата, нажав на клавиатуре клавишу ';', после того как Пролог информирует его о найденном решении. В данном разделе будут представлены диаграммы, показывающие, как Пролог пытается доказать и передоказать целевые утверждения.

<p>2.6.1. Успешное доказательство конъюнкции целевых утверждений</p>

Пролог пытается согласовать с базой данных входящие в конъюнкцию целевые утверждения в том порядке, в каком они написаны (слева направо), где бы они ни появились – в теле правила или в вопросе. Это означает, что Пролог не будет проверять некоторое утверждение, пока не будет доказан его сосед слева. А сосед справа будет рассматриваться только после доказательства данного целевого утверждения. Рассмотрим следующую простую программу о семейных связях:


родители (С,M,F):- мать(С,М), отец(C,F).

мать(джон,анна).

мать(мэри,анна).

отец(мэри,фред). отец(джон,фред).


Давайте рассмотрим последовательность событий, позволяющую дать ответ на вопрос:


?-женщина(мэри), родители(мэри,М,Р), родители(джон,М,Р).



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

Представим целевые утверждения в виде прямоугольников, распределенных по странице. Стрелка, начинающаяся в верхней части страницы, указывает, какие целевые утверждения уже согласованы. Прямоугольники, через которые стрелка уже прошла, соответствуют согласованным целевым утверждениям. Прямоугольники, лежащие ниже острия стрелки, соответствуют целевым утверждениям, которые Пролог еще не рассматривал. При выполнении программы стрелка движется вверх и вниз по странице в соответствии с переходом Пролога от одного целевого утверждения к другому. Будем называть ее цепочкой доказательств.В данном примере стрелка начинается в верхней части страницы, как показано выше. По мере согласования трех целевых утверждений она будет удлиняться вниз, проходя через соответствующие прямоугольники. Конечная ситуация представлена на рис. 2.2. Отметим, что в ходе доказательства согласованности целевых утверждений с базой данных были найдены значения для переменных Ми F.

Такая диаграмма иллюстрирует общую структуру происходящего, но она не показывает, какдоказывались эти три целевых утверждения. Для того чтобы показать это, поместим внутрь прямоугольников больше информации. Давайте посмотрим, как доказывалось второе целевое утверждение. Доказательство согласованности целевого утверждения с базой данных включает в себя поиск в базе данных соответствующих(сопоставимых) утверждений, пометку этого места базы данных и затем доказательств возникших подцелей. Этот процесс для второго целевого утверждения можно проиллюстрировать, включив в прямоугольник родителииндикацию выбранного утверждения и возникшие подцели. Выбранное утверждение обозначается числом в скобках, в данном случае (1). Это число указывает номер выбранного утверждения в наборе утверждений с соответствующим предикатом.Таким образом, число 1означает, что было выбрано первое утверждение с данным предикатом. Эта информация достаточна для отметки места в базе данных. Подцели заключены в маленькие прямоугольники, помещенные в прямоугольник данного целевого утверждения. В момент, когда выбрано утверждение родители,ситуация выглядит так, как показано на рис. 2.3.


Рис. 2.3.

Стрелка вошла в прямоугольник родителии прошла через скобки, указывая, что выбрано некоторое утверждение. Данное утверждение создало две подцели – матьи отец. Вданный момент для получения ответа на вопрос необходимо, чтобы стрелка прошла через два маленьких прямоугольника, вышла из прямоугольника родителии затем прошла через второй прямоугольник родители.Когда стрелка проходит через маленькие прямоугольники, необходимо выполнить те же самые шаги: выбор соответствующего утверждения и доказательство порождаемых им подцелей. В данном примере для каждого из этих двух целевых утверждений в базе данных находится соответствующий факт, и их согласованность с базой данных доказывается. На рис. 2.4 приведено более детальное изображение ситуации в момент получения ответа на вопрос.

Рис. 2.4.

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

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

<p> <i>2.6.2. Рассмотрение целевых утверждений при использовании механизма возврата</i> </p>

Когда целевое утверждение недоказуемо (проверены все возможные утверждения или пользователь нажал клавишу ';'), «цепочка доказательств» проходит назад тот путь, по которому она пришла в данную точку. Она возвращается в покинутые перед этим прямоугольники для того, чтобы попытаться передоказать(вновь согласовать) соответствующие целевые утверждения. Когда стрелка возвращается в то место, где было выбрано какое-то утверждение (это событие изображается числом в скобках), Пролог пытается найти альтернативное утверждение, соответствующее данной цели. Сначала делаются неопределенными все переменные, которые были конкретизированы в ходе доказательства данного целевого утверждения. Затем возобновляется поиск в базе данных, начиная с того места, где был оставлен маркер. Если будет найдено другое утверждение, соответствующее целевому, Пролог помечает это место, и дальше события развиваются, как было описано выше в разд. 2.6.1. Отметим, что рассмотрение любых целевых утверждений, находящихся «ниже» данного (даже если они были пройдены в ходе рассмотрения предыдущей альтернативы), всегда начинается с самого начала. Пролог пытается доказать их без учета положения маркера (т. е. это не передоказательство). Если не удается найти другое подходящее утверждение, данное целевое утверждение считается недоказуемым и стрелка продолжает возвращаться назад до следующего маркера. В нашем примере, если целевое утверждение родители(джон,анна,фред)недоказуемо, стрелка уйдет назад из прямоугольника родители(джон,анна,фред)и войдет в прямоугольник родители (мэри,анна,фред)снизу для того, чтобы попытаться передоказать данное целевое утверждение (см. рис. 2.5).

Рис. 2.5.

Отступая дальше, стрелка достигнет места, где было выбрано утверждение, соответствующее целевому утверждению отец. В первую очередь освобождаются все переменные, которые были конкретизированы в результате использования данного утверждения. Это означает, что переменная Fвновь становится неконкретизированной. Затем Пролог просматривает базу данных, начиная с утверждения, следующего за первым утверждением с предикатом отец(здесь находится маркер), пытаясь найти альтернативное утверждение. Если предположить, что мэриимеет только одного отца, то этот процесс успехом не завершится. Поэтому стрелка продолжит отступление. Она покинет прямоугольник отец(мэри, F)(это целевое утверждение недоказуемо) и вернется в прямоугольник мать(мэри,анна)(для того, чтобы попытаться передоказать данное целевое утверждение) (см. рис. 2.6).


Рис. 2.6.

Отступление стрелки будет продолжаться до успешного доказательства соответствующего целевого утверждения.

Эти примеры иллюстрируют общую схему повторного рассмотрения целевых утверждений в процессе возврата. Когда некоторое целевое утверждение недоказуемо, стрелка возвращается из соответствующего прямоугольника в прямоугольник с предшествующим целевым утверждением. Стрелка отступает до тех пор, пока не встретится маркер. Все переменные, которые были конкретизированы в результате предыдущего выбора сопоставимого утверждения, становятся неконкретизированными. Затем Пролог возобновляет поиск в базе данных сопоставимого утверждения, начиная с маркера. Если сопоставимое утверждение будет найдено, новое место помечается маркером, создаются прямоугольники для целевых подутверждений и стрелка опять начинает движение вниз. В противном случае стрелка продолжает отступать вверх в поисках другого маркера.

<p> <i>2.6.3. Установление соответствия</i> </p>

Правила, определяющие, подходит ли некоторое утверждение для согласования с целевым утверждением, выглядят следующим образом. Отметим, что при выборе утверждения все переменные сначала неконкретизированы.

• Неконкретизированная переменная соответствует любому объекту. Этот объект становится значением переменной.

• Целое число или атом соответствуют только самим себе.

• Между структурами можно установить соответствие, только если они имеют одинаковый функтор, одинаковое число параметров и соответствующие параметры соответствуют друг другу.

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

Если читатель заметил сходство между установлением соответствия и приравниванием аргументов (разд. 2.4), то он совершенно прав. Дело в том, что предикат '=' пытается сделать свои аргументы равными путем установления соответствия между ними.

Попытаемся применить на практике наши знания об операторах, арифметических действиях и установлении соответствия. Предположим, что в базе данных находятся следующие факты:


сумма(5).

сумма(З).

сумма(X+Y).


Рассмотрим вопрос:


?- сумма(2+3).


Какой из вышеприведенных фактов будет соответствовать данному запросу? Если вы думаете, что таковым будет первый факт, вам следует вернуться назад и еще раз прочесть разделы о структурах и операторах. В вопросе аргументом структуры суммаявляется структурас функтором + и компонентами 2 и 3. На самом деле указанной цели соответствует третий факт, при этом переменные Xи Yпринимают конкретные значения 2 и 3.

С другой стороны, если программист действительно хочет вычислить сумму, ему следовало бы воспользоваться предикатом is. Он должен был бы написать


?- X is 2+3.


или (в качестве развлечения) он мог бы определить предикат сложить, связывающий два целых числа и их сумму:


сложить (X, Y, Z):- Z is X+Y.


В этом определении Xи Yдолжны быть конкретизированы, а Zнеконкретизирована.

ГЛАВА 3. ИСПОЛЬЗОВАНИЕ СТРУКТУР ДАННЫХ

Оксфордский толковый словарь английского языка определяет слово «рекурсия» следующим образом:

РЕКУРСИЯ. [Теперь употребляется редко, устаревшее.] Обратное движение, возвращение.

Это определение загадочно и, по-видимому, устаревшее. В настоящее время рекурсия является очень популярным и мощным средством в области нечислового программирования. Она используется в двух случаях: для описания структур, имеющих другие структуры в качестве компонент, и для описания программ, выполнению которых предшествует выполнение их собственной копии. Иногда начинающие программисты относятся к рекурсии с подозрением, не понимая, как это можно определить некоторое отношение через само себя? В Прологе рекурсия – это нормальный и естественный способ представления структур данных и программ. Мы надеемся, что тема этой главы – рекурсия – обретает ясность удобным и ненавязчивым образом.

3.1. Структуры и деревья

Чтобы легче было понять сложную структуру, ее обычно представляют в виде дерева,в котором каждому функтору соответствует вершина, а компонентам соответствуют ветви дерева. Каждая ветвь может указывать на другую структуру, так что мы можем иметь структуры внутри структур. Обычно принято изображать дерево таким образом, чтобы корень дерева находился вверху, а ветви были направлены вниз, как это показано на рис. 3.1. Заметим, что два последних дерева имеют одинаковую форму, хотя корни и листья деревьев различны. Прежде чем читать дальше, вы должны быть уверены в том, что можете представить в виде дерева каждую из структур, с которыми вы уже сталкивались в предыдущих главах.


  • Страницы:
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24