Консультация № 176012
13.01.2010, 03:34
43.34 руб.
0 1 1
Доброго времени суток, уважаемые эксперты! Очень нужна помощь с бинарным деревом. Тип дерева: Упорядоченое бинарное дерево
Элемент дерева - книга : автор , название , год издания , количество страниц , издательство. Нужно сделать добавление элемента в дерево, удаление заданного элемента из дерева, и поиск в дереве по году издания. Вот мой код, я попытался сделать добавление элемента в дерево, и вывод в таблицу. Упорядоченное по строке адрес. Но если вводить их по алфавиту, то добавляются правльно один за другим. А если, нужно вставить элемент в середину, или перед, то происходит замена. Вообщем данные порятятся. Буду рад вашим откликам : )


Приложение:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, Grids, Menus;

type
tp=^el;
el=record
avtor:string[50];
title:string[70];
year:integer;
pages:integer;
press:string[50];
ls,rs:tp;
end;

TForm1 = class(TForm)
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
ComboBox2: TComboBox;
ComboBox3: TComboBox;
ComboBox4: TComboBox;
ComboBox5: TComboBox;
Sg: TStringGrid;
BitBtn1: TBitBtn;
ComboBox1: TComboBox;
MainMenu1: TMainMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
N5: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure IniTree(var P:tp);
procedure InRight (var P: tp);
procedure InLeft (var P: tp);
procedure Tree_Add (P: tp);
procedure PrintTree1(var R: tp; L:byte);
procedure BitBtn1Click(Sender: TObject);
procedure N5Click(Sender: TObject);
procedure N4Click(Sender: TObject);
private
{ Private declarations }
root:tp;
public
{ Public declarations }
end;

var

Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
sg.ColWidths[0]:=20;
Sg.Cells[0,0]:='№';
Sg.Cells[1,0]:='Автор';
Sg.Cells[2,0]:='Название';
Sg.Cells[3,0]:='Год издания';
Sg.Cells[4,0]:='Кол-во страниц';
Sg.Cells[5,0]:='Издательство';
end;

procedure TForm1.PrintTree1(var R: tp; L:byte);// просмотр дерева
var i: Byte;
begin
if R <> nil then
begin
sg.RowCount:=1;
PrintTree1(R^.rs, L+1);
Sg.RowCount:=sg.RowCount+1;
sg.FixedRows:=1;
for i := 1 to L do
begin
Sg.Cells[0,i]:=inttostr(i);
Sg.Cells[1,i]:=r^.avtor;
Sg.Cells[2,i]:=r^.title;
Sg.Cells[3,i]:=inttostr(r^.year);
Sg.Cells[4,i]:=inttostr(r^.pages);
Sg.Cells[5,i]:=r^.Press;
end;
PrintTree1(R^.ls, L+1);
end;
end;

procedure TForm1.IniTree(var P: tp); //создание корня дерева
begin
New(P);
p^.avtor:=ComboBox1.Text;
p^.title:=ComboBox2.Text;
p^.year:=strtoint(ComboBox3.Text);
p^.pages:=strtoint(ComboBox4.Text);
p^.press:=ComboBox5.Text;
P^.ls := nil;
P^.rs := nil;
end;

procedure TForm1.InRight (var P: tp); //добавить узел справа
var R : tp;
begin
New(R);
r^.avtor:=ComboBox1.Text;
r^.title:=ComboBox2.Text;
r^.year:=strtoint(ComboBox3.Text);
r^.pages:=strtoint(ComboBox4.Text);
r^.press:=ComboBox5.Text;
R^.ls := nil;
R^.rs := nil;
P^.rs := R;
end;

procedure TForm1.InLeft (var P: tp); //добавление узла слева
var R : tp;
begin
New(R);
r^.avtor:=ComboBox1.Text;
r^.title:=ComboBox2.Text;
r^.year:=strtoint(ComboBox3.Text);
r^.pages:=strtoint(ComboBox4.Text);
r^.press:=ComboBox5.Text;
R^.ls := nil;
R^.rs := nil;
P^.ls := R;
end;

procedure TForm1.Tree_Add (P: tp); // решаем куда добавлять
var OK: Boolean;
r:tp;
begin
OK := false;
while not OK do begin
if ComboBox1.Text > P^.avtor then //посмотреть направо
if P^.rs <> nil //правый узел не nil
then P := P^.rs //обход справа
else
begin //правый узел - лист и надо добавить к нему элемент
InRight (P); //и конец
OK := true;
end
else //посмотреть налево
if P^.ls <> nil //левый узел не nil
then P := P^.ls //обход слева
else
begin //левый узел -лист и надо добавить к нему элемент
InLeft(P); //и конец
OK := true
end;
end; //цикла while
end;


procedure TForm1.BitBtn1Click(Sender: TObject);
begin
if ComboBox1.Text='' then
begin
MessageDlg('Заполните поле "Автор"!', mtError, [mbOk], 0);
exit;
end
else
if ComboBox2.Text='' then
begin
MessageDlg('Заполните поле "Название"!', mtError, [mbOk], 0);
exit;
end
else
if ComboBox3.Text='' then
begin
MessageDlg('Заполните поле "Год издания"!', mtError, [mbOk], 0);
exit;
end
else
if ComboBox4.Text='' then
begin
MessageDlg('Заполните поле "Количество страниц"!', mtError, [mbOk], 0);
exit;
end
else
if ComboBox5.Text='' then
begin
MessageDlg('Заполните поле "Издательство"!', mtError, [mbOk], 0);
exit;
end;
if root=Nil then IniTree(Root)
else Tree_Add(Root);
ComboBox1.Text:='';
ComboBox2.Text:='';
ComboBox3.Text:='';
ComboBox4.Text:='';
ComboBox5.Text:='';
PrintTree1(Root, 1);
end;





procedure TForm1.N5Click(Sender: TObject);
begin
close;
end;

procedure TForm1.N4Click(Sender: TObject);
begin
form2.show;
end;

end.

Обсуждение

давно
Профессионал
304622
583
13.01.2010, 14:21
общий
это ответ
Здравствуйте, Камынин Владислав Дмитриевич.

Нет, данные не портятся. Всё в дереве укладывается правильно. Ошибка в выводе -- процедуре PrintTree1. Честно говоря, когда я увидел этот цикл for, то слегка обалдел. Это излишнее мудрствование, только ради того, чтобы не очищать сетку перед вызовом рекурсии.

Короче. Надо, чтобы рекурсивном вызове PrintTree1 было просто добавление очередной строки в таблицу и вызовы рекурсий. При чём _сначала_ влево, а _потом_ вправо. L вообще не нужна. А перед первым вызовом, надо специально очищать сетку. Код в приложении.

Приложение:
// Рекурсия

procedure TForm1.PrintTree1(var R: tp);// просмотр дерева
var i: Byte;
begin
if R <> nil then
begin
PrintTree1(R^.ls);
Sg.RowCount:=sg.RowCount+1;
sg.FixedRows:=1;
i:=Sg.RowCount-1;
Sg.Cells[0,i]:=inttostr(i);
Sg.Cells[1,i]:=r^.avtor;
Sg.Cells[2,i]:=r^.title;
Sg.Cells[3,i]:=inttostr(r^.year);
Sg.Cells[4,i]:=inttostr(r^.pages);
Sg.Cells[5,i]:=r^.Press;
PrintTree1(R^.rs);
end;
end;

// Вызов рекурсии в BitBtn1Click
sg.RowCount:=1;
PrintTree1(Root);
Форма ответа