where : ibrtses delphi
Delphi - string tree
disclaimer
the source code of this page may not appear correctly in certain browsers
due to special characters. Have a look at the source of this HTML page
with notepad instead
string tree usage
Storing strings in a tree can have advantages. This component allows storing
strings together with a number.
Use it as :
VAR
ST:TStringTree;
Code:integer;
s:shortstring;
ST:=TStringTree.create;
ST.lowercase:=true; // converts all new strings to lowercase
code:=1;
ST.addstring('Symbol1',code);
code:=2;
ST.addstring('Symbol2',code);
if ST.findstring('Symbol3',code) then { code holds the assigned number }
else { string not there }
the code
unit StringTree;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
stdctrls;
type
CodeType=integer;
TCharObj =class(TObject)
terminal:boolean;
ch:char;
code:CodeType;
prev,next:TCharObj;
up,dn:TCharObj;
constructor create(c:char);
destructor destroyall;
end;
TStringTree = class(TObject)
private
{ Private declarations }
fhead:TCharObj;
fsize:integer;
fcase:boolean;
protected
{ Protected declarations }
procedure appendstring(s:shortstring;from:byte;var at:TCharObj;z:CodeType; mode:byte);
function insertstring(s:shortstring;from:byte;var at:TCharObj;var z:CodeType):boolean;
function _findstring(s:shortstring;from:byte;var at:TCharObj;var z:CodeType):boolean;
public
{ Public declarations }
constructor create;
destructor destroy;
function addstring(s:shortstring;var z:CodeType):boolean; // true if added, false if there+code
function findstring(s:shortstring;var z:Codetype):boolean; // true if found, returns code
published
{ Published declarations }
property size:integer read fsize;
property lowercase:boolean read fcase write fcase;
property head:TCharObj read fhead;
end;
procedure Register;
implementation
procedure lowercasestring(var s:shortstring);
var i:integer;
begin
for i:=1 to length(s) do begin
if (s[i]>='A')and (s[i]<='Z') then s[i]:=chr(ord(s[i])+$20);
end;
end;
//..................................................
constructor TCharObj.create(c:char);
begin
inherited create;
terminal:=false;
ch:=c;
code:=0;
next:=nil;prev:=nil;
up:=nil;dn:=nil;
end;
destructor TCharObj.destroyall;
begin
if next<>nil then next.destroyall;
if dn<>nil then dn.destroyall;
inherited destroy;
end;
//..................................................
constructor TStringTree.create;
begin
inherited create;
fhead:=nil;
fsize:=0;
fcase:=false;
end;
destructor TStringTree.destroy;
var p:TCharobj;
begin
if fhead<>nil then fhead.destroyall;
inherited destroy;
end;
// mode 0 - new, 1 - next, 2 - up, 3 - down
procedure TStringTree.appendstring(s:shortstring;from:byte;var at:TCharObj;z:CodeType; mode:byte);
var p,v:TCharObj;
i:integer;
begin
v:=at;
for i:=from to length(s) do begin
p:=TCharObj.create(s[i]);
if (i=from) then begin // the first of these
case mode of
0: at:=p; // head
1: begin at.next:=p; p.prev:=at; end; // next
2: begin
p.dn:=at; p.up:=at.up; if p.up<>nil then p.up.dn:=p; // up
p.prev:=at.prev; if p.up=nil then begin
if p.prev<>nil then p.prev.next:=p
else fhead:=p;
end;
at.up:=p;
end;
3: begin
p.dn:=at.dn; p.up:=at; if p.dn<>nil then p.dn.up:=p; // down
p.prev:=at.prev;
at.dn:=p;
end;
end; //case
end
else begin
v.next:=p;
p.prev:=v;
end;
v:=p;
inc(fSize);
end;
p.terminal:=true;
p.code:=z;
end;
function TStringTree.insertstring(s:shortstring;from:byte;var at:TCharObj;var z:CodeType):boolean;
var v,l,p:TCharObj;
found:boolean;
begin
if at=nil then begin // just append the linear rest
appendstring(s,from,at,z,0);
result:=true;
end
else begin // there is a next
found:=false; v:=at; l:=v;
repeat
if (ord(v.ch)nil) then begin // there is a next letter
l:=v; v:=v.dn;
end
else begin // there is no next letter
appendstring(s,from,v,z,3);
found:=true;
result:=true;
end;
end
else begin // pos reached
if (ord(v.ch)=ord(s[from])) then begin // pos found
if (from < length(s)) then
result:=insertstring(s,from+1,v.next,z)
else begin
if v.terminal then begin // symbol exists
result:=false;
z:=v.code;
end
else begin // char exists, but not the symbol
v.terminal:=true;
v.code:=z;
result:=true;
end;
end;
found:=true;
end
else begin // bigger insert before
appendstring(s,from,v,z,2);
result:=true;
found:=true;
end;
end;
until found;
end;
end;
function TStringTree._findstring(s:shortstring;from:byte;var at:TCharObj;var z:CodeType):boolean;
var v,l,p:TCharObj;
found:boolean;
begin
if at=nil then begin // just append the linear rest
result:=false;
end
else begin // there is a next
found:=false; v:=at; l:=v;
repeat
if (ord(v.ch)nil) then begin // there is a next letter
l:=v; v:=v.dn;
end
else begin // there is no next letter
result:=false;
found:=true;
end;
end
else begin // pos reached
if (ord(v.ch)=ord(s[from])) then begin // pos found
if (from < length(s)) then result:=_findstring(s,from+1,v.next,z)
else begin
if v.terminal then begin
result:=true;
z:=v.code;
end
else result:=false;
end;
found:=true;
end
else begin // bigger insert before
result:=false;
found:=true;
end;
end;
until found;
end;
end;
function TStringTree.addstring(s:shortstring;var z:CodeType):boolean;
var u:shortstring;
begin
u:=s;
if fcase then lowercasestring(u);
result:=insertstring(u,1,fhead,z);
end;
function TStringTree.findstring(s:shortstring;var z:Codetype):boolean; // true if found, returns code
var u:shortstring;
begin
u:=s;
if fcase then lowercasestring(u);
result:=_findstring(u,1,fhead,z);
end;
procedure Register;
begin
// RegisterComponents('Samples', [TStringTree]);
end;
end.
Feedback is welcome
sponsored links
Delphi
home
last updated: 29.jan.01
Copyright (99,2001) Ing.Büro R.Tschaggelar