{Insert values into a binary tree using a recursive disk file search as an example} {uncommented source code followed by commented source code} {http://www.awitness.org/delphi_pascal_tutorial/source/insert_binary_tree.html} unit disk_search; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, FileCtrl; type link=^node; node=record filename:string; ModTime:integer; l, r:link end; TForm1 = class(TForm) FileSearch: TButton; TreePrint: TButton; procedure FormCreate(Sender: TObject); procedure FileSearchClick(Sender: TObject); function FileLook(Filespec:string):boolean; Function TreeInsert(Fname:string; q:link):link; procedure TreePrintClick(Sender: TObject); Procedure PrintTree(q:link); private { Private declarations } public { Public declarations } end; var Form1: TForm1; head, tail: link; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin new(tail); new(head); head^.filename:=''; head^.r:=tail; head^.l:=tail; end; procedure TForm1.FileSearchClick(Sender: TObject); var found:boolean; begin Found:=FileLook('f:\somefiles\*.*'); If found then MessageDlg('DUN!', mtInformation, [mbOk], 0) else MessageDlg('Directory does not exist', mtError, [mbOk], 0); end; Function TForm1.FileLook(Filespec:string):boolean; var x:link; validres, ModifiedTime:integer; SearchRec : TSearchRec; DirPath, FullName, Flname : string; begin DirPath:=ExtractFilePath(FileSpec); Result:= DirectoryExists(DirPath); If not Result then exit; Flname:=ExtractFileName(FileSpec); validres := FindFirst(FileSpec, faAnyFile, SearchRec); while validres=0 do begin If (SearchRec.Name[1] <> '.') then begin {not a directory} FullName:=DirPath + LowerCase(SearchRec.Name); x:=TreeInsert(FullName, head); ModifiedTime:=FileAge(FullName); x^.ModTime:=ModifiedTime; If (SearchRec.Attr and faDirectory>0) then FileLook(FullName+'\'+Flname); end; validres:=FindNext(SearchRec); end; end; Function TForm1.TreeInsert(Fname:string; q:link):link; var st:link; begin repeat st:=q; if fnametail then begin PrintTree(q^.l); Writeln(fs, q^.filename); PrintTree(q^.r); end; end; end. {commented source code} Function TForm1.FileLook(Filespec:string):boolean; var x:link; {declare a local binary tree link...this will be used to receive the return value from the TreeInsert function so that the ModifiedDate value can be inserted into the correct node next to the filespec} validres, ModifiedTime:integer; {create integer for modtime} SearchRec : TSearchRec; DirPath, FullName, Flname : string; begin DirPath:=ExtractFilePath(FileSpec); Result:= DirectoryExists(DirPath); If not Result then exit; Flname:=ExtractFileName(FileSpec); validres := FindFirst(FileSpec, faAnyFile, SearchRec); while validres=0 do begin If (SearchRec.Name[1] <> '.') then begin FullName:=DirPath + LowerCase(SearchRec.Name); x:=TreeInsert(FullName, head); {pass the filename and the 'head' (or 'root) pointer to the binary tree to the tree insert routine, and receive back in 'x' pointer the location at which the filename was inserted into the tree} ModifiedTime:=FileAge(FullName);{find mod date of file} x^.ModTime:=ModifiedTime; {use the 'x' pointer value returned by the TreeInsert function to insert the value into the last modified time of the file into the correct node of the tree beside the filename} If (SearchRec.Attr and faDirectory>0) then FileLook(FullName+'\'+Flname); end; {end if} validres:=FindNext(SearchRec); end; {end while} end; Function TForm1.TreeInsert(Fname:string; q:link):link; {pass the tree insert function the name of the file, and the 'head' or root pointer to the tree. The filename will function as the 'key' or sorting value for insertion into the tree for example 'apple' would be less than 'orange' files on the 'c:\' drive less than the 'd:\' drive etc.} var st:link; {create a local binary link to keep track of the position in the tree just before the spot where the insertion will take place...The search will continue as long as the insertion key value is less than or greater than the value in the 'q' pointer. The new value will be inserted as a 'leaf' in the tree at the spot where there is no 'branch' attached to the insertion node (the node then will be equal to the tail which is the signal to insert the new value ... to understand how this works you might try diagraming a very simply tree and then stepping through the code to see what happens graphically... It will be neccesary to have the address of the preceding link stored in 'st' so that it can then be adjusted to point to the inserted link} begin repeat st:=q; if fnametail then begin {when the recursive calls finally hit a 'dead end' (the tail) the stacked up calls will begin returning and depending on whether or not they were called from the left or the right they will on returning hit the appropriate print statement} PrintTree(q^.l); Writeln(fs, q^.filename); PrintTree(q^.r); end; {end if} end;