Files
lazarus-ccr/applications/cactusjukebox/source/MGTree16.pas
sekelsenmat 6f8c048343 Adds the cactus jukebox to the lazarus ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1748 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2011-07-21 09:39:48 +00:00

269 lines
6.8 KiB
ObjectPascal
Executable File

(******************************************************************************
Massimo Magnano 08-11-2004.
File : MGTree16.pas REV. 1.1
Implementazione di un albero per la memorizzazione di 2^32 Dati a 32 Bit.
Nel caso peggiore si hanno 16 passi tra i nodi per la ricerca di un dato
Implementation of a tree to store 2^32 Data of 32 Bit.
In the worst case you have 16 walk on the nodes for data research
******************************************************************************)
unit MGTree16;
{$mode delphi}{$H+}
interface
//{$O-}
Type
PMGTree16Data =^TMGTree16Data;
TMGTree16Data = packed record
Data :Integer;
UData :TObject;
Nodes :array[0..3] of PMGTree16Data;
end;
PPMGTree16Data =^PMGTree16Data;
TWalkFunction = procedure (Tag:Integer; Data :Integer; UData :TObject) of object;
TMGTree16 = class
protected
pRoot :PMGTree16Data;
Allocated :Cardinal;
function allocData :PMGTree16Data;
procedure deallocData(pData :PMGTree16Data);
function InternalFind(Value :Integer; var pParent :PMGTree16Data;
var ValNode :Byte) :PMGTree16Data;
public
constructor Create;
destructor Destroy; override;
function Add(Data:Integer; UData :TObject=nil; pNode :PMGTree16Data=Nil) : PMGTree16Data;
function Del(Data :Integer) : Boolean;
function Find(Value :Integer; var Data :Integer; var UData :TObject) : Boolean;
procedure WalkOnTree(Tag:Integer; WalkFunction :TWalkFunction);
procedure Clear(Tag:Integer=0; WalkFunction :TWalkFunction=Nil);
end;
implementation
constructor TMGTree16.Create;
begin
Allocated :=0;
pRoot :=Self.allocData;
end;
destructor TMGTree16.Destroy;
begin
Self.Clear;
FreeMem(pRoot);
inherited Destroy;
end;
function TMGTree16.allocData :PMGTree16Data;
begin
GetMem(Result, sizeof(TMGTree16Data));
FillChar(Result^, sizeof(TMGTree16Data), 0);
Inc(Allocated, sizeof(TMGTree16Data));
end;
procedure TMGTree16.deallocData(pData :PMGTree16Data);
begin
FreeMem(pData, sizeof(TMGTree16Data));
Dec(Allocated, sizeof(TMGTree16Data));
end;
//Add a new node on tree, if pNode <> nil add pNode else create a new node and
//assign to it Data, UData
// Return : the node just created or nil if error
function TMGTree16.Add(Data :Integer; UData :TObject=nil; pNode :PMGTree16Data=Nil) : PMGTree16Data;
Var
ValNode :Byte; //0..3
i :Integer;
pParent,
pData :PMGTree16Data;
iValue :Integer;
begin
pData :=pRoot;
Result :=Nil;
if (pNode<>Nil)
then Data :=pNode^.Data;
iValue :=Data;
for i:=0 to 15 do
begin
ValNode := (Data and $00000003);
pParent :=pData;
pData :=pData^.Nodes[ValNode];
if (pData=Nil)
then begin
if pNode=Nil
then begin
pData :=Self.allocData;
pData^.Data :=iValue;
pData^.UData :=UData;
end
else pData :=pNode;
pParent^.Nodes[ValNode] :=pData;
Result :=pData;
Exit;
end;
if (pData^.Data=iValue)
then begin
Result :=pData;
Exit;
end;
Data :=Data shr 2;
end;
end;
//Del the node that have Data as ID, if node have subnode attached to it
// reinsert in correct position.
function TMGTree16.Del(Data :Integer) : Boolean;
Var
pData,
pParent :PMGTree16Data;
ValNode, i :Byte;
begin
pData :=InternalFind(Data, pParent, ValNode);
Result := (pData<>Nil);
if Result
then begin
//Reinserisco le (foglie <> Nil) del nodo che si sta per eliminare
pParent^.Nodes[ValNode] :=pData^.Nodes[ValNode]; //bypass
for i:=0 to 3 do
begin
if (i<>ValNode) and (pData^.Nodes[i]<>Nil)
then Add(0, nil, pData^.Nodes[i]);
end;
Self.deallocData(pData);
end;
end;
//Find the node that have Value as ID
//Return :
// pParent = Parent of the Node
// ValNode = sub Node on were i'm attached in Parent
// Result = the Node
function TMGTree16.InternalFind(Value :Integer; var pParent :PMGTree16Data;
var ValNode :Byte) :PMGTree16Data;
Var
i :Integer;
pData :PMGTree16Data;
iValue :Integer;
begin
pData :=pRoot;
iValue :=Value;
Result :=Nil;
for i:=0 to 15 do
begin
ValNode := (Value and $00000003);
pParent :=pData;
pData :=pData^.Nodes[ValNode];
if (pData=Nil)
then begin
Result :=Nil;
Exit;
end;
if (pData^.Data=iValue)
then begin
Result :=pData;
Exit;
end;
Value :=Value shr 2;
end;
end;
//User Visible Find, search for node that have Value as ID
//Return : Data, UData = Node data
// Result = True if find
function TMGTree16.Find(Value :Integer; var Data :Integer; var UData :TObject) : Boolean;
Var
pData,
pParent :PMGTree16Data;
ValNode :Byte;
begin
pData :=InternalFind(Value, pParent, ValNode);
Result := (pData<>Nil);
if Result
then begin
Data :=pData^.Data;
UData :=pData^.UData;
end;
end;
//Recursivly Walk on tree and call user defined function on every node
procedure TMGTree16.WalkOnTree(Tag:Integer; WalkFunction :TWalkFunction);
procedure __Walk(pData :PMGTree16Data);
Var
i :Byte;
begin
for i :=0 to 3 do
begin
if pData^.Nodes[i]<>Nil
then begin
__Walk(pData^.Nodes[i]);
if Assigned(WalkFunction)
then WalkFunction(Tag, pData^.Nodes[i]^.Data, pData^.Nodes[i]^.UData);
end;
end;
end;
begin
__Walk(pRoot);
end;
//Recursivly delete node on tree, first call user defined function on every node.
procedure TMGTree16.Clear(Tag:Integer=0; WalkFunction :TWalkFunction=Nil);
procedure __Clear(pData :PMGTree16Data);
Var
i :Byte;
begin
for i :=0 to 3 do
begin
if pData^.Nodes[i]<>Nil
then begin
__Clear(pData^.Nodes[i]);
if Assigned(WalkFunction)
then WalkFunction(Tag, pData^.Nodes[i]^.Data, pData^.Nodes[i]^.UData);
Self.deallocData(pData^.Nodes[i]);
pData^.Nodes[i] :=Nil;
end;
end;
end;
begin
__Clear(pRoot);
end;
end.