Уважаемый glupo.
Давайте попробуем разобраться:
Итак, в начальный момент времени Вы создаёте переменную
Tree, поэтому при первом вызове процедуры
AddLeaf переменная
a заведомо не равна Nil, но при этом значение её полей не определено (вернее, зависит от компилятора: может быть "куча мусора" или все нули). Что уже приводит к нежелательным последствиям: как минимум, у Вас в выходном массиве будет на 1 элемент больше, если же компилятор не обнуляет вновь созданную переменную, то возможны как ошибки доступа, так и "вечные" циклы (одна случайная непустая область памяти даст ссылку на другую, которая ...).
Далее,
- Код: Выделить всё
while y <> nil do begin
if x^.data < y^.data then y := y^.left else y := y^.right;
end;
в общем случае не работает.
Представьте, что у Вас в некий момент времени в дереве хранятся 4 числа: 1, 2, 4, 5. Корень дерева — 2. А Вам нужно в дерево вставить число 3.
Тогда: 3>2 => y=4, цикл не завершен, на следующем шаге 3<4 => y=2, цикл не завершен, повторять пока не надоест...
Но, даже если Вам повезло, и число нужно вставить в начало или конец дерева, Вы строкой
- Код: Выделить всё
x := y;
приравниваете
x Nil, ведь, по условию, цикл завершается только при y=Nil.
Я тут вчерне набросал вариант решения:
- Код: Выделить всё
procedure AddLeaf(var a : ptr; b : integer); {добавление эл-та}
var
p, x:Ptr;
StepRight:Boolean;
begin
if a=nil then begin
// Writeln('First =', b);
New(a);
a^.Data:=b;
a^.Left:=nil;
a^.Right:=nil
end else begin
if a^.Data<b then StepRight:=True else StepRight:=False;
p:=a;
if StepRight then begin
While p^.Data<b do begin
// writeln(p^.Data,' < ',b);
if p^.Right=nil then begin
StepRight:=not(StepRight);
Break
end else p:=p^.Right;
end;
end else begin
While p^.Data>=b do begin
// writeln(p^.Data,' >= ',b);
if p^.Left=nil then begin
StepRight:=not(StepRight);
Break
end else p:=p^.Left;
end;
end;
New(x);
x^.Data:=b;
if StepRight then begin
x^.Left:=p^.Left;
if p^.Left<>nil then p^.Left^.Right:=x;
x^.Right:=p;
p^.Left:=x
end else begin
x^.Right:=p^.Right;
if p^.Right<>nil then p^.Right^.Left:=x;
x^.Left:=p;
p^.Right:=x
end;
{ Write('Вставим ', x^.Data, ' между ');
if x^.Left=nil then Write ('Nil и ') else Write (x^.Left^.Data,' и ');
if x^.Right=nil then WriteLn ('Nil') else WriteLn (x^.Right^.Data);}
end;
// PrintTree(a)
end;
.
Теперь о выводе дерева на экран: задумка несомненно красивая, однако, в том виде, который Вы предложили — гарантированно не работоспособная (дерево уже из 2 элементов будет распечатываться вечность, поскольку из процедуры печати первого будет вызвана процедура печати второго, из которой будут вызвана процедура печати первого, из которой...).
Рискну предложить такой вариант
- Код: Выделить всё
procedure PrintTree(a : ptr); {обход дерева в обратном порядке}
var
x:ptr;
begin
x:=a;
While x^.Left<>Nil do x:=x^.Left;
while x<>Nil do begin
if x=a then Write('[',x^.Data,'] ') else Write(x^.Data,' ');
x:=x^.Right
end;
WriteLn
end;
.
Надеюсь, что смог помочь.
С уважением, Алексей.