1
0
mirror of synced 2024-09-19 09:46:09 +00:00

Added: TX2UtCustomBTree base class

This commit is contained in:
Mark van Renswoude 2004-07-23 13:15:14 +00:00
parent 0e708e29d5
commit 02fc3996a7

View File

@ -50,6 +50,8 @@ type
procedure Clear(); procedure Clear();
procedure Push(const ANode: PX2UtBTreeNode); procedure Push(const ANode: PX2UtBTreeNode);
function Pop(): PX2UtBTreeNode; function Pop(): PX2UtBTreeNode;
procedure Reverse();
end; end;
{ {
@ -57,20 +59,21 @@ type
:: This class implements a binary tree of pointer values. :: This class implements a binary tree of pointer values.
} }
TX2UtBTree = class(TObject) TX2UtCustomBTree = class(TObject)
private private
FRoot: PX2UtBTreeNode; FRoot: PX2UtBTreeNode;
FCursor: PX2UtBTreeNode; FCursor: PX2UtBTreeNode;
FIsReset: Boolean; FIsReset: Boolean;
FParent: TX2UtBTreeStack; FParent: TX2UtBTreeStack;
protected
function GetItem(Index: Cardinal): Pointer; function GetItem(Index: Cardinal): Pointer;
procedure SetItem(Index: Cardinal; const Value: Pointer); procedure SetItem(Index: Cardinal; const Value: Pointer);
function GetCurrentIndex(): Cardinal; function GetCurrentIndex(): Cardinal;
function GetCurrentValue(): Pointer; function GetCurrentValue(): Pointer;
protected
function LookupNode(const AIndex: Cardinal; function LookupNode(const AIndex: Cardinal;
const ACreate: Boolean = True): PX2UtBTreeNode; virtual; const ACreate: Boolean = False;
const ACursor: Boolean = False): PX2UtBTreeNode; virtual;
procedure NewNode(const AParent: PX2UtBTreeNode; procedure NewNode(const AParent: PX2UtBTreeNode;
var ANode: PX2UtBTreeNode; var ANode: PX2UtBTreeNode;
@ -84,17 +87,33 @@ type
property Root: PX2UtBTreeNode read FRoot; property Root: PX2UtBTreeNode read FRoot;
property IsReset: Boolean read FIsReset write FIsReset; property IsReset: Boolean read FIsReset write FIsReset;
property Parent: TX2UtBTreeStack read FParent; property Parent: TX2UtBTreeStack read FParent;
//:$ Gets or sets an item.
property Items[Index: Cardinal]: Pointer read GetItem
write SetItem; default;
//:$ Returns the index at the current cursor location.
property CurrentIndex: Cardinal read GetCurrentIndex;
//:$ Returns the value at the current cursor location.
property CurrentValue: Pointer read GetCurrentValue;
public public
constructor Create(); constructor Create();
destructor Destroy(); override; destructor Destroy(); override;
//:$ Clears the tree //:$ Clears the tree.
procedure Clear(); procedure Clear();
//:$ Deletes a node from the tree //:$ Deletes a node from the tree.
procedure Delete(const AIndex: Cardinal); procedure Delete(const AIndex: Cardinal);
//:$ Resets the node cursor //:$ Checks if an index exists in the tree.
//:: If the ASetCursor parameter is set to True, the cursor will be
//:: positioned at the item if it is found.
function Exists(const AIndex: Cardinal; const ASetCursor: Boolean = False): Boolean;
//:$ Resets the node cursor.
//:: The node cursor can be used to traverse through the binary tree. //:: The node cursor can be used to traverse through the binary tree.
//:: Call Reset first, followed by Next to get the first item. You can //:: Call Reset first, followed by Next to get the first item. You can
//:: continue to call Next until it returns false. The CurrentIndex and //:: continue to call Next until it returns false. The CurrentIndex and
@ -103,27 +122,29 @@ type
//:! until the next Reset call. //:! until the next Reset call.
procedure Reset(); procedure Reset();
//:$ Moves the node cursor to the next node //:$ Moves the node cursor to the next node.
//:! The order in which nodes are traversed is from top to bottom, left //:! The order in which nodes are traversed is from top to bottom, left
//:! to right. Do not depend on the binary tree to sort the output. //:! to right. Do not depend on the binary tree to sort the output.
function Next(): Boolean; function Next(): Boolean;
end;
//:$ Gets or sets an item. {
property Items[Index: Cardinal]: Pointer read GetItem :$ Binary tree implementation
write SetItem; default;
//:$ Returns the index at the current cursor location :: This class exposes TX2UtCustomBTree's properties
property CurrentIndex: Cardinal read GetCurrentIndex; }
TX2UtBTree = class(TX2UtCustomBTree)
//:$ Returns the value at the current cursor location public
property CurrentValue: Pointer read GetCurrentValue; property Items;
property CurrentIndex;
property CurrentValue;
end; end;
{ {
:$ Binary tree implementation for integer values :$ Binary tree implementation for integer values
} }
TX2UtIntegerBTree = class(TX2UtBTree) TX2UtIntegerBTree = class(TX2UtBTree)
private protected
function GetItem(Index: Cardinal): Integer; function GetItem(Index: Cardinal): Integer;
procedure SetItem(Index: Cardinal; const Value: Integer); procedure SetItem(Index: Cardinal; const Value: Integer);
function GetCurrentValue(): Integer; function GetCurrentValue(): Integer;
@ -140,7 +161,7 @@ type
:$ Binary tree implementation for string values :$ Binary tree implementation for string values
} }
TX2UtStringBTree = class(TX2UtBTree) TX2UtStringBTree = class(TX2UtBTree)
private protected
function GetItem(Index: Cardinal): String; function GetItem(Index: Cardinal): String;
procedure SetItem(Index: Cardinal; const Value: String); procedure SetItem(Index: Cardinal; const Value: String);
function GetCurrentValue(): String; function GetCurrentValue(): String;
@ -166,10 +187,7 @@ const
CStackSize = 32; CStackSize = 32;
type type
PStringRecord = ^TStringRecord; PString = ^String;
TStringRecord = record
Value: String;
end;
{======================== TX2UtBTreeStack {======================== TX2UtBTreeStack
@ -215,10 +233,30 @@ begin
end; end;
{============================= TX2UtBTree procedure TX2UtBTreeStack.Reverse;
var
iCount: Integer;
iIndex: Integer;
pSwap: PX2UtBTreeNode;
begin
if FPosition = -1 then
exit;
iCount := (FPosition + 1) div 2;
for iIndex := 0 to iCount - 1 do
begin
pSwap := FItems[iIndex];
FItems[iIndex] := FItems[FPosition - iIndex];
FItems[FPosition - iIndex] := pSwap;
end;
end;
{======================= TX2UtCustomBTree
Initialization Initialization
========================================} ========================================}
constructor TX2UtBTree.Create; constructor TX2UtCustomBTree.Create;
begin begin
inherited; inherited;
@ -226,7 +264,7 @@ begin
FParent := TX2UtBTreeStack.Create(); FParent := TX2UtBTreeStack.Create();
end; end;
destructor TX2UtBTree.Destroy; destructor TX2UtCustomBTree.Destroy;
begin begin
FreeAndNil(FParent); FreeAndNil(FParent);
DeleteNode(FRoot); DeleteNode(FRoot);
@ -235,10 +273,10 @@ begin
end; end;
{============================= TX2UtBTree {======================= TX2UtCustomBTree
Tree Management Tree Management
========================================} ========================================}
function TX2UtBTree.LookupNode; function TX2UtCustomBTree.LookupNode;
var var
pNode: PX2UtBTreeNode; pNode: PX2UtBTreeNode;
@ -250,7 +288,15 @@ begin
begin begin
InitNode(pNode); InitNode(pNode);
pNode^.Index := AIndex; pNode^.Index := AIndex;
Result := pRoot; Result := pNode;
if ACursor then
begin
Parent.Clear();
IsReset := False;
Cursor := pNode;
end;
exit; exit;
end; end;
@ -292,10 +338,24 @@ begin
end; end;
end; end;
end; end;
if ACursor and Assigned(Result) then
begin
// Trace parents
pNode := Result^.Parent;
while Assigned(pNode) do
begin
Parent.Push(pNode);
pNode := pNode^.Parent;
end;
// Parents are now in reverse order
Parent.Reverse();
end;
end; end;
procedure TX2UtBTree.NewNode; procedure TX2UtCustomBTree.NewNode;
begin begin
New(ANode); New(ANode);
FillChar(ANode^, SizeOf(TX2UtBTreeNode), #0); FillChar(ANode^, SizeOf(TX2UtBTreeNode), #0);
@ -306,12 +366,12 @@ begin
InitNode(ANode); InitNode(ANode);
end; end;
procedure TX2UtBTree.InitNode; procedure TX2UtCustomBTree.InitNode;
begin begin
// Reserved for descendants // Reserved for descendants
end; end;
procedure TX2UtBTree.DeleteNode; procedure TX2UtCustomBTree.DeleteNode;
begin begin
if Assigned(ANode^.Left) then if Assigned(ANode^.Left) then
DeleteNode(ANode^.Left); DeleteNode(ANode^.Left);
@ -332,39 +392,45 @@ begin
end; end;
procedure TX2UtBTree.Clear; procedure TX2UtCustomBTree.Clear;
begin begin
DeleteNode(FRoot); DeleteNode(FRoot);
NewNode(nil, FRoot, False); NewNode(nil, FRoot, False);
end; end;
procedure TX2UtBTree.Delete; procedure TX2UtCustomBTree.Delete;
var var
pItem: PX2UtBTreeNode; pItem: PX2UtBTreeNode;
begin begin
pItem := LookupNode(AIndex, False); pItem := LookupNode(AIndex);
if Assigned(pItem) then if Assigned(pItem) then
DeleteNode(pItem); DeleteNode(pItem);
end; end;
function TX2UtCustomBTree.Exists;
begin
Result := Assigned(LookupNode(AIndex, False, True));
end;
{============================= TX2UtBTree
{======================= TX2UtCustomBTree
Tree Traversing Tree Traversing
========================================} ========================================}
procedure TX2UtBTree.ClearCursor; procedure TX2UtCustomBTree.ClearCursor;
begin begin
Cursor := nil; Cursor := nil;
end; end;
procedure TX2UtBTree.Reset; procedure TX2UtCustomBTree.Reset;
begin begin
Cursor := Root; Cursor := Root;
IsReset := True; IsReset := True;
end; end;
function TX2UtBTree.Next; function TX2UtCustomBTree.Next;
var var
pParent: PX2UtBTreeNode; pParent: PX2UtBTreeNode;
pCurrent: PX2UtBTreeNode; pCurrent: PX2UtBTreeNode;
@ -418,7 +484,7 @@ begin
end; end;
end; end;
function TX2UtBTree.GetCurrentIndex; function TX2UtCustomBTree.GetCurrentIndex;
begin begin
if Assigned(Cursor) and (not IsReset) then if Assigned(Cursor) and (not IsReset) then
Result := Cursor^.Index Result := Cursor^.Index
@ -426,7 +492,7 @@ begin
raise EX2UtBTreeInvalidCursor.Create(RSInvalidCursor); raise EX2UtBTreeInvalidCursor.Create(RSInvalidCursor);
end; end;
function TX2UtBTree.GetCurrentValue; function TX2UtCustomBTree.GetCurrentValue;
begin begin
if Assigned(Cursor) and (not IsReset) then if Assigned(Cursor) and (not IsReset) then
Result := Cursor^.Value Result := Cursor^.Value
@ -435,26 +501,26 @@ begin
end; end;
{============================= TX2UtBTree {======================= TX2UtCustomBTree
Items Items
========================================} ========================================}
function TX2UtBTree.GetItem; function TX2UtCustomBTree.GetItem;
var var
pItem: PX2UtBTreeNode; pItem: PX2UtBTreeNode;
begin begin
Result := nil; Result := nil;
pItem := LookupNode(Index, False); pItem := LookupNode(Index);
if Assigned(pItem) then if Assigned(pItem) then
Result := pItem^.Value; Result := pItem^.Value;
end; end;
procedure TX2UtBTree.SetItem; procedure TX2UtCustomBTree.SetItem;
var var
pItem: PX2UtBTreeNode; pItem: PX2UtBTreeNode;
begin begin
pItem := LookupNode(Index); pItem := LookupNode(Index, True);
if Assigned(pItem) then if Assigned(pItem) then
pItem^.Value := Value; pItem^.Value := Value;
end; end;
@ -488,9 +554,9 @@ var
begin begin
Result := ''; Result := '';
pItem := LookupNode(Index, False); pItem := LookupNode(Index);
if Assigned(pItem) then if Assigned(pItem) then
Result := PStringRecord(pItem^.Value)^.Value; Result := PString(pItem^.Value)^;
end; end;
procedure TX2UtStringBTree.SetItem; procedure TX2UtStringBTree.SetItem;
@ -498,35 +564,35 @@ var
pItem: PX2UtBTreeNode; pItem: PX2UtBTreeNode;
begin begin
pItem := LookupNode(Index); pItem := LookupNode(Index, True);
if Assigned(pItem) then if Assigned(pItem) then
PStringRecord(pItem^.Value)^.Value := Value; PString(pItem^.Value)^ := Value;
end; end;
function TX2UtStringBTree.GetCurrentValue; function TX2UtStringBTree.GetCurrentValue;
var var
pValue: PStringRecord; pValue: PString;
begin begin
Result := ''; Result := '';
pValue := inherited GetCurrentValue(); pValue := inherited GetCurrentValue();
if Assigned(pValue) then if Assigned(pValue) then
Result := pValue^.Value; Result := pValue^;
end; end;
procedure TX2UtStringBTree.DeleteNode;
begin
Dispose(PStringRecord(ANode^.Value));
inherited;
end;
procedure TX2UtStringBTree.InitNode; procedure TX2UtStringBTree.InitNode;
begin begin
inherited; inherited;
New(PStringRecord(ANode^.Value)); New(PString(ANode^.Value));
end;
procedure TX2UtStringBTree.DeleteNode;
begin
Dispose(PString(ANode^.Value));
inherited;
end; end;
end. end.