uses crt; type PListItem = ^TListItem; PPerson = ^TPerson; TListItem = record next: PListItem; PersonRef: PPerson; end; TList = record head: PListItem; Count: integer; end; TPerData = record Name: string; end; TPerson = record Parent: PPerson; PersonData: TPerData; Level: integer; ChildList: TList; end; TTree = record Root: PPerson; ItemList: TList; end; {There are some procedures to work with the PersonRef List} {Initialization of the PersonRef List} procedure InitList(var List: TList); begin List.head:= nil; List.Count:= 0; end; {Add Data to tail of the List} procedure AddToList(var List: TList; Data: PPerson); var CurEl, NewEl: PListItem; begin new(NewEl); NewEl^.PersonRef:= Data; NewEl^.Next:= nil; inc(List.Count); if List.Head = nil then begin List.Head:= NewEl; exit; end; CurEl:= List.Head; while CurEl^.Next <> nil do CurEl:= CurEl^.Next; CurEl^.Next:= NewEl; end; {Find previous element before Ptr} function FindPred(var List: TList; ptr: PListItem): PListItem; var tmp: PListItem; begin tmp:= List.Head; while tmp <> nil do if tmp^.Next = ptr then begin FindPred:= tmp; exit; end else tmp:= tmp^.Next; FindPred:= nil; end; {Delete element from List by its Reference Ref} procedure DeleteElement(var List: TList; ptr: PListItem); var tmp: PListItem; begin if List.Head = nil then exit; if ptr = List.Head then List.Head:= ptr^.Next else begin tmp:= FindPred(List, ptr); tmp^.Next:= ptr^.Next; end; dispose(ptr); dec(List.Count); end; procedure DeleteValue(var List: TList; value: PPerson); var CurEl: PListItem; begin CurEl:= List.Head; While CurEl <> nil do if CurEl^.PersonRef = value then begin DeleteElement(List, CurEl); exit; end else CurEl:= CurEl^.Next; end; {Delete elements of the List.} procedure ClearList(var List: TList); var CurEl: PListitem; begin CurEl:= List.Head; While CurEl <> nil do begin List.Head:= CurEl^.Next; dispose(CurEl); CurEl:= List.Head; end; end; {Print Index list} procedure PrintList(var List: TList); var CurEl: PListItem; i, k, number: integer; begin WriteLn('0. Root'); number:= 1; if List.Head = nil then exit; CurEl:= List.Head; k:= ABS(CurEl^.PersonRef^.Level); While CurEl <> nil do begin Write(' ', number,'.'); GotoXY(CurEl^.PersonRef^.Level + k + 5, WhereY); WriteLn(CurEl^.PersonRef^.PersonData.Name, ' (',CurEl^.PersonRef^.Level, ')'); CurEl:= CurEl^.Next; inc(number); end; end; {Конец работы со списком} {=====================================} {Работа с деревом} {Initialization of the Tree} procedure Init (var tree: TTree); begin Tree.Root:= nil; InitList(Tree.ItemList); {AddToList(Tree.ItemList, nil);} end; procedure GetFree (var Ref: PPerson); var tmp: PPerson; begin new (tmp); InitList(tmp^.ChildList); Ref:= tmp; end; {Add to ChildList's Tail of the Person element} procedure AddChild (Person, ChildRef: PPerson); begin AddToList(Person^.ChildList, ChildRef); end; {Add element to Root of the tree} procedure AddToTreeRoot (var tree: TTree; Data: TPerData); var Person: PPerson; begin GetFree(Person); Person^.Parent:= nil; Person^.PersonData:= Data; If Tree.Root = nil then Person^.Level:= 0 else begin Person^.Level:= Tree.Root^.Level - 1; Tree.Root^.Parent:= Person; AddChild(Person, Tree.Root); end; Tree.Root:= Person; end; {Add PersonRef element to the Parent element} procedure AddPerson(var Tree: TTree; Parent: PPerson; Data: TPerData); var Person: PPerson; begin if Parent = nil then begin AddToTreeRoot(Tree, Data); exit; end; GetFree(Person); Person^.Parent:= Parent; Person^.PersonData:= Data; Person^.Level:= Parent^.Level + 1; AddChild(Parent, Person); end; {Indexate of the Tree from Ref element. Adds elements to Index list.} procedure IndexTree (var Tree: TTree; Ref: PPerson); var curEl: PListItem; begin if Tree.Root = nil then Exit; CurEl:= Ref^.ChildList.Head; {for i:= 0 to Ref^.Level do Write (' ');} {WriteLn(Ref^.PersonData.Name);} AddToList(Tree.ItemList, Ref); While CurEl <> nil do begin IndexTree(Tree, CurEl^.PersonRef); CurEl:= CurEl^.Next; end; end; procedure Kill (var tree: TTree; Ref: PPerson); var curEl: PListItem; begin CurEl:= Ref^.ChildList.Head; While CurEl <> nil do begin Kill(Tree, CurEl^.PersonRef); CurEl:= CurEl^.Next; end; ClearList(Ref^.ChildList); dispose(Ref); end; procedure KillPerson(var Tree: TTree; Ref: PPerson); var List: TList; Level: integer; CurEl: PListItem; begin {сначала удалим данного человека из списка его родителя} List:= ref^.Parent^.ChildList; {Удаляем элемент, ссылающийся на REf (Его значением будет ref)} DeleteValue(List, ref); {Теперь можно всех убить...} Kill (tree, ref); end; procedure Printer(Ref: PPerson); var curEl: PListItem; begin if Ref = nil then Exit; CurEl:= Ref^.ChildList.Head; WriteLn(Ref^.PersonData.Name); While CurEl <> nil do begin Printer(CurEl^.PersonRef); CurEl:= CurEl^.Next; end; end; {Выводит дерево на экран} procedure PrintTree(var Tree: TTree); begin {Чистим индексный список} ClearList(Tree.ItemList); {Записываем структуру дерева в упорядоченный список} IndexTree(Tree, Tree.Root); {Печатаем индексный список} PrintList(Tree.ItemList); end; {Конец работы с деревом} {Work with menu} {Find reference by its number in the list} {Возвращает ссылку на ЭЛЕМЕНТ СПИСКА List. Для обращен} function FindRef(var List: TList; n: integer): PPerson; var i: integer; CurEl: PListItem; begin if n = 0 then begin FindRef:= nil; exit; end; CurEl:= List.Head; for i:= 1 to n-1 do if CurEl <> nil then CurEl:= CurEl^.Next else begin FindRef:= nil; exit; end; FindRef:= CurEl^.PersonRef; end; var Tree: TTree; User: TPerData; IsExit: boolean; n, i: integer; name: String; Data: TPerData; Ref: PPerson; list: TList; begin isExit := false; Init(Tree); TextMode(256); DAta.Name:= ''; for i:= 0 to 5 do begin ClrScr; Writeln(''); PrintTree(Tree); Write('Select number of Element: '); readln(n); Write('Enter persons name: '); Readln(Data.Name); AddPerson(Tree, FindRef(Tree.ItemList, n), Data); end; ClrScr; PrintTree(tree); WriteLn('What Person do you want to delete? '); Readln(n); Ref:= FindRef(Tree.ItemList, n); KillPerson(Tree, Ref); clrscr; {Посмотрим, что получилось на самом деле} Printer(Tree.Root); readln; end.