Для выполнения этого задания, как и для подавляющего большинства других заданий на обработку деревьев, следует воспользоваться вспомогательной
Таким образом, решение задачи будет иметь следующий вид:
uses PT4;
function NodeCount(P: PNode): integer;
begin
if P = nil then
result := 0
else
result := 1 + NodeCount(P^.Left) + NodeCount(P^.Right);
end;
var P1: PNode;
begin
Task('Tree2');
read(P1);
write(NodeCount(P1));
end.
Цепочка рекурсивных вызовов функции NodeCount завершается при достижении терминальной вершины (листа), у которой поля Left и Right равны nil. Благодаря наличию функции NodeCount, раздел операторов программы является очень кратким: в нем считывается адрес P1 корня исходного дерева, после чего вызывается функция NodeCount(P1), возвращаемое значение которой сразу выводится процедурой write.
Запустив эту программу пять раз, мы получим сообщение
Рассмотренная выше реализация бинарных деревьев позволяет легко переходить от родительских вершин к их дочерним вершинам, но не допускает обратного перехода. В то же время, для некоторых задач, связанных с обработкой деревьев, возможность обратного перехода от потомков к их предку позволяет получить более простое решение. Ясно, что для обеспечения возможности обратного перехода каждую вершину дерева надо снабдить еще одним полем связи, в котором должна храниться ссылка на ее родительскую вершину. Это поле связи естественно назвать Parent. Поскольку корень дерева предка не имеет, его поле Parent должно быть равно nil.
Деревья, вершины которых содержат информацию о своих родителях, будем называть
Tree49°. Дан указатель
Запустив программу-заготовку, созданную для задания Tree49, мы увидим в области исходных данных изображение обычного" бинарного дерева, в то время как в области результатов будет изображено дерево с обратной связью, вершины которого связаны не одинарными, а двойными линиями.
Обратите также внимание на то, что в области результатов отсутствуют какие-либо данные, кроме измененного дерева. Это означает, что в программе, решающей задачу, не требуется использовать процедуры вывода; достаточно лишь преобразовать исходное дерево требуемым образом. Поскольку при таком преобразовании адрес корня дерева
Для преобразования исходного дерева в дерево с обратной связью необходимо задать правильные значения для полей Parent всех вершин дерева, перебирая эти вершины с помощью подходящей рекурсивной процедуры. В эту процедуру удобно передавать в качестве параметров не только указатель P на текущую вершину, но и указатель Par на предка этой вершины:
uses PT4;
procedure SetParent(P, Par: PNode);
begin
if P = nil then
exit;
P^.Parent := Par;
SetParent(P^.Left, P);
SetParent(P^.Right, P);
end;
var P1: PNode;
begin
Task('Tree49');
read(P1);
SetParent(P1, nil);
end.
При стартовом запуске рекурсивной процедуры SetParent в качестве второго параметра указывается nil.