mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-21 23:19:29 +02:00
lazutils: added TIndexedAVLTree
git-svn-id: trunk@36146 -
This commit is contained in:
parent
a124aba76d
commit
ba291b44cc
@ -150,8 +150,36 @@ type
|
||||
function NodeToReportStr(aNode: TAvgLvlTreeNode): string; virtual;
|
||||
function ReportAsString: string;
|
||||
end;
|
||||
TAvgLvlTreeClass = class of TAvgLvlTree;
|
||||
PAvgLvlTree = ^TAvgLvlTree;
|
||||
|
||||
type
|
||||
TIndexedAVLTreeNode = class(TAvgLvlTreeNode)
|
||||
public
|
||||
LeftCount: SizeInt; // number of nodes in the Left side
|
||||
end;
|
||||
|
||||
{ TIndexedAVLTree }
|
||||
|
||||
TIndexedAVLTree = class(TAvgLvlTree)
|
||||
private
|
||||
function GetItems(Index: SizeInt): Pointer; inline;
|
||||
protected
|
||||
fLastIndex: SizeInt;
|
||||
fLastNode: TIndexedAVLTreeNode;
|
||||
procedure DeletingNode(aNode: TAvgLvlTreeNode); override;
|
||||
procedure Init; override;
|
||||
procedure NodeAdded(aNode: TAvgLvlTreeNode); override;
|
||||
procedure RotateLeft(aNode: TAvgLvlTreeNode); override;
|
||||
procedure RotateRight(aNode: TAvgLvlTreeNode); override;
|
||||
procedure SwitchPositionWithSuccessor(aNode, aSuccessor: TAvgLvlTreeNode); override;
|
||||
public
|
||||
function GetNodeAtIndex(Index: integer): TIndexedAVLTreeNode;
|
||||
property Items[Index: SizeInt]: Pointer read GetItems;
|
||||
procedure ConsistencyCheck; override;
|
||||
function NodeToReportStr(aNode: TAvgLvlTreeNode): string; override;
|
||||
end;
|
||||
|
||||
type
|
||||
{ TPointerToPointerTree - Associative array }
|
||||
|
||||
@ -1803,6 +1831,166 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TIndexedAVLTree }
|
||||
|
||||
function TIndexedAVLTree.GetItems(Index: SizeInt): Pointer;
|
||||
begin
|
||||
Result:=GetNodeAtIndex(Index).Data;
|
||||
end;
|
||||
|
||||
procedure TIndexedAVLTree.DeletingNode(aNode: TAvgLvlTreeNode);
|
||||
var
|
||||
aParent: TAvgLvlTreeNode;
|
||||
begin
|
||||
fLastNode:=nil;
|
||||
repeat
|
||||
aParent:=aNode.Parent;
|
||||
if (aParent=nil) then exit;
|
||||
if aParent.Left=aNode then
|
||||
TIndexedAVLTreeNode(aParent).LeftCount-=1;
|
||||
aNode:=aParent;
|
||||
until false;
|
||||
end;
|
||||
|
||||
procedure TIndexedAVLTree.Init;
|
||||
begin
|
||||
FNodeClass:=TIndexedAVLTreeNode;
|
||||
end;
|
||||
|
||||
procedure TIndexedAVLTree.NodeAdded(aNode: TAvgLvlTreeNode);
|
||||
var
|
||||
aParent: TAvgLvlTreeNode;
|
||||
begin
|
||||
fLastNode:=nil;
|
||||
repeat
|
||||
aParent:=aNode.Parent;
|
||||
if (aParent=nil) then exit;
|
||||
if aParent.Left=aNode then
|
||||
TIndexedAVLTreeNode(aParent).LeftCount+=1;
|
||||
aNode:=aParent;
|
||||
until false;
|
||||
end;
|
||||
|
||||
procedure TIndexedAVLTree.RotateLeft(aNode: TAvgLvlTreeNode);
|
||||
{ Parent Parent
|
||||
| |
|
||||
CurNode => OldRight
|
||||
/ \ /
|
||||
Left OldRight CurNode
|
||||
/ / \
|
||||
OldRightLeft Left OldRightLeft }
|
||||
var
|
||||
CurNode: TIndexedAVLTreeNode absolute aNode;
|
||||
OldRight: TIndexedAVLTreeNode;
|
||||
begin
|
||||
OldRight:=TIndexedAVLTreeNode(aNode.Right);
|
||||
inherited RotateLeft(aNode);
|
||||
OldRight.LeftCount += 1+CurNode.LeftCount;
|
||||
end;
|
||||
|
||||
procedure TIndexedAVLTree.RotateRight(aNode: TAvgLvlTreeNode);
|
||||
{ Parent Parent
|
||||
| |
|
||||
CurNode => OldLeft
|
||||
/ \ \
|
||||
OldLeft Right CurNode
|
||||
\ / \
|
||||
OldLeftRight OldLeftRight Right }
|
||||
var
|
||||
CurNode: TIndexedAVLTreeNode absolute aNode;
|
||||
OldLeft: TIndexedAVLTreeNode;
|
||||
begin
|
||||
OldLeft:=TIndexedAVLTreeNode(aNode.Left);
|
||||
inherited RotateRight(aNode);
|
||||
CurNode.LeftCount -= (1 + OldLeft.LeftCount);
|
||||
end;
|
||||
|
||||
procedure TIndexedAVLTree.SwitchPositionWithSuccessor(aNode,
|
||||
aSuccessor: TAvgLvlTreeNode);
|
||||
var
|
||||
CurNode: TIndexedAVLTreeNode absolute aNode;
|
||||
CurSucc: TIndexedAVLTreeNode absolute aSuccessor;
|
||||
h: SizeInt;
|
||||
begin
|
||||
h:=CurNode.LeftCount;
|
||||
CurNode.LeftCount:=CurSucc.LeftCount;
|
||||
CurSucc.LeftCount:=h;
|
||||
inherited SwitchPositionWithSuccessor(aNode, aSuccessor);
|
||||
end;
|
||||
|
||||
function TIndexedAVLTree.GetNodeAtIndex(Index: integer): TIndexedAVLTreeNode;
|
||||
|
||||
procedure RaiseOutOfBounds;
|
||||
begin
|
||||
raise Exception.Create('TIndexedAVLTree: Index '+IntToStr(Index)+' out of bounds 0..'+IntToStr(Count));
|
||||
end;
|
||||
|
||||
begin
|
||||
if (Index<0) or (Index>=Count) then
|
||||
RaiseOutOfBounds;
|
||||
|
||||
if fLastNode<>nil then begin
|
||||
if Index=fLastIndex then
|
||||
exit(fLastNode)
|
||||
else if Index=fLastIndex+1 then begin
|
||||
fLastIndex:=Index;
|
||||
fLastNode:=TIndexedAVLTreeNode(fLastNode.Successor);
|
||||
exit(fLastNode);
|
||||
end else if Index=fLastIndex-1 then begin
|
||||
fLastIndex:=Index;
|
||||
fLastNode:=TIndexedAVLTreeNode(fLastNode.Precessor);
|
||||
exit(fLastNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
fLastIndex:=Index;
|
||||
Result:=TIndexedAVLTreeNode(Root);
|
||||
repeat
|
||||
if Result.LeftCount>Index then
|
||||
Result:=TIndexedAVLTreeNode(Result.Left)
|
||||
else if Result.LeftCount=Index then begin
|
||||
fLastNode:=TIndexedAVLTreeNode(Result);
|
||||
exit;
|
||||
end
|
||||
else begin
|
||||
Index -= Result.LeftCount+1;
|
||||
Result:=TIndexedAVLTreeNode(Result.Right);
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
procedure TIndexedAVLTree.ConsistencyCheck;
|
||||
|
||||
procedure E(Msg: string);
|
||||
begin
|
||||
raise Exception.Create('TIndexedAVLTree.ConsistencyCheck: '+Msg);
|
||||
end;
|
||||
|
||||
var
|
||||
Node: TAvgLvlTreeNode;
|
||||
i: SizeInt;
|
||||
LeftCount: SizeInt;
|
||||
begin
|
||||
inherited ConsistencyCheck;
|
||||
i:=0;
|
||||
for Node in Self do begin
|
||||
if Node.Left<>nil then
|
||||
LeftCount:=Node.Left.GetCount
|
||||
else
|
||||
LeftCount:=0;
|
||||
if TIndexedAVLTreeNode(Node).LeftCount<>LeftCount then
|
||||
E(Format('Node.LeftCount=%d<>%d',[TIndexedAVLTreeNode(Node).LeftCount,LeftCount]));
|
||||
if GetNodeAtIndex(i)<>Node then
|
||||
E(Format('GetNodeAtIndex(%d)<>%P',[i,Node]));
|
||||
inc(i);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TIndexedAVLTree.NodeToReportStr(aNode: TAvgLvlTreeNode): string;
|
||||
begin
|
||||
Result:=inherited NodeToReportStr(aNode)+' LeftCount='+IntToStr(TIndexedAVLTreeNode(aNode).LeftCount);
|
||||
end;
|
||||
|
||||
{$IFDEF DisableNewStringToStringTree}
|
||||
{ TOldStringToStringTree }
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
Test specific with:
|
||||
./runtests --format=plain --suite=TestAVLTreeAddsDeletes
|
||||
./runtests --format=plain --suite=TestIndexedAVLTreeAddsDeletes
|
||||
}
|
||||
unit TestAvgLvlTree;
|
||||
|
||||
@ -21,9 +22,12 @@ type
|
||||
|
||||
TTestAvgLvlTree = class(TTestCase)
|
||||
private
|
||||
fTreeClass: TAvgLvlTreeClass;
|
||||
procedure TestSequence(Args: array of const);
|
||||
procedure TestAVLTree;
|
||||
published
|
||||
procedure TestAVLTreeAddsDeletes;
|
||||
procedure TestIndexedAVLTreeAddsDeletes;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -36,7 +40,7 @@ var
|
||||
i: Integer;
|
||||
Value: LongInt;
|
||||
begin
|
||||
Tree:=TAvgLvlTree.Create;
|
||||
Tree:=fTreeClass.Create;
|
||||
//DebugLn(Tree.ReportAsString);
|
||||
Tree.ConsistencyCheck;
|
||||
|
||||
@ -68,7 +72,7 @@ begin
|
||||
Tree.Free;
|
||||
end;
|
||||
|
||||
procedure TTestAvgLvlTree.TestAVLTreeAddsDeletes;
|
||||
procedure TTestAvgLvlTree.TestAVLTree;
|
||||
begin
|
||||
// rotate left
|
||||
TestSequence([]);
|
||||
@ -96,8 +100,18 @@ begin
|
||||
TestSequence([1,2,3,-2,-3,-1]);
|
||||
TestSequence([1,2,3,-3,-1,-2]);
|
||||
TestSequence([1,2,3,-3,-2,-1]);
|
||||
end;
|
||||
|
||||
//
|
||||
procedure TTestAvgLvlTree.TestAVLTreeAddsDeletes;
|
||||
begin
|
||||
fTreeClass:=TAvgLvlTree;
|
||||
TestAVLTree;
|
||||
end;
|
||||
|
||||
procedure TTestAvgLvlTree.TestIndexedAVLTreeAddsDeletes;
|
||||
begin
|
||||
fTreeClass:=TIndexedAVLTree;
|
||||
TestAVLTree;
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
Loading…
Reference in New Issue
Block a user