Title: A Simple Tree Class
Question: How do I create a Tree Class
Answer:
A Simple Tree Class
Here is a simple tree class
To add nodes first create a TTreeNode object and then use the AddNode function of the TTree class
-Code-
unit TreeClass;
interface
uses
classes,sysutils;
type
TTreeNode=class;
TErrorObject = class(Exception);
TTree=class
private
fremoveall:boolean;
findex:integer;
fRootnode:Ttreenode;
fnodes:Tlist;
function GetNodeFromIndex(index:integer):TTreeNode;
function GetCount:integer;
public
constructor Create;
destructor destroy;override;
function AddNode(parentnode:TTreeNode):TTreeNode;
procedure RemoveNode(anode:TTreeNode);
procedure Clear;
property Count:integer read GetCount;
property RootNode:TTreenode read frootnode;
property Item[index:integer]:TTreenode read GetnodeFromIndex;
end;
TTreenode=class
private
ptree:TTree;
findex:integer;
frelindex:integer;
flevel:integer;
fdata:pointer;
fchildren:Tlist;
fparent:TTreenode;
function GetNode(index:integer):TTreeNode;
function GetCount:integer;
function GetNextSibling:TTreenode;
function GetFirstSibling:TTreeNode;
public
constructor create(atree:TTree);
destructor destroy;override;
procedure Clear;
property Tree:Ttree read ptree;
property AbsoluteIndex:integer read findex;
property RelativeIndex:integer read frelindex;
property Level:integer read flevel;
property Count:integer read GetCount;
property Data:pointer read fdata write fdata;
property Children[Index:integer]:TTreenode read GetNode;
property NextSibling:TTreeNode read GetNextSibling;
property FirstSibling:TTreeNode read GetFirstSibling;
property Parent:TTreenode read fparent;
end;
procedure RaiseError(const msg:string);
implementation
function TTree.GetCount:integer;
begin
result:=fnodes.count;
end;
function TTree.GetNodeFromIndex(index:integer):TTreeNode;
begin
result:=nil;
if (index=0) and (index result:=TTreeNode(fnodes[index])
else
RaiseError('Range Out of Bounds');
end;
procedure TTree.clear;
var
i:integer;
tmp:TTreeNode;
begin
fremoveall:=true;
findex:=1;
for i:= 1 to fnodes.count-1 do
begin
tmp:=TTreeNode(fnodes[i]);
freeandnil(tmp);
end;
fnodes.clear;
frootnode.fchildren.clear;
fnodes.add(frootnode);
fremoveall:=false;
end;
constructor TTreenode.create(atree:TTree);
begin
ptree:=atree;
findex:=ptree.findex;
inc(ptree.findex);
fchildren:=Tlist.create;
fdata:=nil;
fparent:=atree.fRootnode;
end;
destructor TTreenode.destroy;
var
i:integer;
tmp:TTreeNode;
begin
if ptree.fremoveall=false then
begin
ptree.fnodes.remove(self);
for i:=0 to fchildren.count-1 do
begin
tmp:=TTreeNode(fchildren[i]);
freeandnil(tmp);
end;
freeandnil(fchildren);
end;
ptree:=nil;
fparent:=nil;
fdata:=nil;
inherited;
end;
function TTreenode.GetCount:integer;
begin
result:=fchildren.Count;
end;
function TTreenode.GetNode(index:integer):TTreeNode;
begin
result:=nil;
if (index =0) and (index result:=fchildren[index]
else
RaiseError('Range Out of Bounds');
end;
function TTreenode.GetNextSibling:TTreenode;
var
i,tmp1:integer;
begin
result:=nil;
tmp1:=-1;
if fparentnil then
begin
for i:=0 to fparent.count-1 do
if fparent.children[i]=self then
begin
tmp1:=i;
break;
end;
if tmp1-1 then
if tmp1 result:=fparent.fchildren[tmp1];
end;
end;
function TTreenode.GetFirstSibling:TTreeNode;
begin
if fparentnil then
result:=fparent.fchildren[0]
else
result:=self;
end;
procedure TTreenode.Clear;
var
i:integer;
tmp:TTreeNode;
begin
for i:=0 to fchildren.count-1 do
begin
tmp:=TTreeNode(fchildren[i]);
freeandnil(tmp);
end;
fchildren.clear;
frelindex:=1;
end;
constructor TTree.Create;
begin
findex:=0;
fremoveall:=false;
fRootnode:=TTreenode.create(self);
frootnode.fparent:=nil;
frootnode.flevel:=0;
fnodes:=Tlist.create;
fnodes.add(frootnode);
end;
destructor TTree.destroy;
begin
clear;
fremoveall:=true;
freeandnil(frootnode);
freeandnil(fnodes);
inherited;
end;
function TTree.AddNode(parentnode:TTreeNode):TTreeNode;
begin
if parentnode=nil then
raiseerror('Invalid Parent Node');
result:=TTreenode.create(self);
result.ptree:=self;
result.fparent:=parentnode;
result.fdata:=nil;
parentnode.fchildren.add(result);
result.frelindex:=parentnode.fchildren.indexof(result);
result.flevel:=parentnode.flevel+1;
fnodes.Add(result);
end;
procedure TTree.RemoveNode(anode:TTreeNode);
var
i:integer;
begin
if anode=frootnode then
RaiseError('Cannot remove root node');
anode.fparent.fchildren.Remove(anode);
fnodes.Remove(anode);
for i:=0 to anode.fchildren.Count-1 do
begin
anode.children[i].fparent:=anode.fparent;
anode.fparent.fchildren.Add(anode.fchildren[i]);
anode.children[i].frelindex:=anode.fparent.fchildren.indexof(anode.fchildren[i]);
anode.children[i].flevel:=anode.fparent.flevel+1;
end;
freeandnil(anode);
end;
procedure RaiseError(const msg:string);
begin
raise TerrorObject.Create(msg);
end;
end.