mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 07:59:28 +02:00
avglvltree: Node.Successor/Precessor
git-svn-id: trunk@36145 -
This commit is contained in:
parent
33958d7756
commit
a124aba76d
@ -50,10 +50,10 @@ type
|
||||
Parent, Left, Right: TAvgLvlTreeNode;
|
||||
Balance: integer; // = RightDepth-LeftDepth -2..+2, after balancing: -1,0,+1
|
||||
Data: Pointer;
|
||||
function FindSuccessor: TAvgLvlTreeNode; // next right
|
||||
function FindPrecessor: TAvgLvlTreeNode; // next left
|
||||
function Successor: TAvgLvlTreeNode; // next right
|
||||
function Precessor: TAvgLvlTreeNode; // next left
|
||||
function TreeDepth: integer; // longest WAY down. e.g. only one node => 0 !
|
||||
procedure ConsistencyCheck(Tree: TAvgLvlTree);
|
||||
procedure ConsistencyCheck(Tree: TAvgLvlTree); virtual;
|
||||
function GetCount: SizeInt;
|
||||
end;
|
||||
TAvgLvlTreeNodeClass = class of TAvgLvlTreeNode;
|
||||
@ -84,10 +84,13 @@ type
|
||||
FOnObjectCompare: TObjectSortCompare;
|
||||
procedure BalanceAfterInsert(ANode: TAvgLvlTreeNode);
|
||||
procedure BalanceAfterDelete(ANode: TAvgLvlTreeNode);
|
||||
procedure DeletingNode({%H-}aNode: TAvgLvlTreeNode); virtual;
|
||||
function FindInsertPos(Data: Pointer): TAvgLvlTreeNode;
|
||||
procedure Init; virtual;
|
||||
procedure NodeAdded({%H-}aNode: TAvgLvlTreeNode); virtual;
|
||||
procedure RotateLeft(aNode: TAvgLvlTreeNode); virtual;
|
||||
procedure RotateRight(aNode: TAvgLvlTreeNode); virtual;
|
||||
procedure SwitchPositionWithSuccessor(aNode, aSuccessor: TAvgLvlTreeNode); virtual;
|
||||
procedure SetOnCompare(const AValue: TListSortCompare);
|
||||
procedure SetOnObjectCompare(const AValue: TObjectSortCompare);
|
||||
procedure SetCompares(const NewCompare: TListSortCompare;
|
||||
@ -142,8 +145,9 @@ type
|
||||
function GetEnumeratorHighToLow: TAvgLvlTreeNodeEnumerator;
|
||||
|
||||
// consistency
|
||||
procedure ConsistencyCheck;
|
||||
procedure ConsistencyCheck; virtual;
|
||||
procedure WriteReportToStream(s: TStream);
|
||||
function NodeToReportStr(aNode: TAvgLvlTreeNode): string; virtual;
|
||||
function ReportAsString: string;
|
||||
end;
|
||||
PAvgLvlTree = ^TAvgLvlTree;
|
||||
@ -439,12 +443,12 @@ function TAvgLvlTreeNodeEnumerator.MoveNext: Boolean;
|
||||
begin
|
||||
if FLowToHigh then begin
|
||||
if FCurrent<>nil then
|
||||
FCurrent:=FCurrent.FindSuccessor
|
||||
FCurrent:=FCurrent.Successor
|
||||
else
|
||||
FCurrent:=FTree.FindLowest;
|
||||
end else begin
|
||||
if FCurrent<>nil then
|
||||
FCurrent:=FCurrent.FindPrecessor
|
||||
FCurrent:=FCurrent.Precessor
|
||||
else
|
||||
FCurrent:=FTree.FindHighest;
|
||||
end;
|
||||
@ -683,7 +687,7 @@ var
|
||||
begin
|
||||
Node:=FindNode(Name);
|
||||
if Node<>nil then
|
||||
Node:=Node.FindSuccessor;
|
||||
Node:=Node.Successor;
|
||||
Result:=GetNode(Node,NextName,NextValue);
|
||||
end;
|
||||
|
||||
@ -694,7 +698,7 @@ var
|
||||
begin
|
||||
Node:=FindNode(Name);
|
||||
if Node<>nil then
|
||||
Node:=Node.FindPrecessor;
|
||||
Node:=Node.Precessor;
|
||||
Result:=GetNode(Node,PrevName,PrevValue);
|
||||
end;
|
||||
|
||||
@ -708,7 +712,7 @@ begin
|
||||
while Node<>nil do begin
|
||||
Item:=PStringToStringItem(Node.Data);
|
||||
Result:=Result+Item^.Name+'='+Item^.Value+LineEnding;
|
||||
Node:=Node.FindSuccessor;
|
||||
Node:=Node.Successor;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -724,7 +728,7 @@ begin
|
||||
while Node<>nil do begin
|
||||
Item:=PStringToStringItem(Node.Data);
|
||||
Values[Item^.Name]:=Item^.Value;
|
||||
Node:=Node.FindSuccessor;
|
||||
Node:=Node.Successor;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -811,10 +815,12 @@ begin
|
||||
// insert to the right
|
||||
InsertPos.Right:=ANode;
|
||||
end;
|
||||
NodeAdded(ANode);
|
||||
BalanceAfterInsert(ANode);
|
||||
end else begin
|
||||
fRoot:=ANode;
|
||||
ANode.Parent:=nil;
|
||||
NodeAdded(ANode);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -930,6 +936,13 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TAvgLvlTree.DeletingNode(aNode: TAvgLvlTreeNode);
|
||||
// called by Delete
|
||||
// Node.Left=nil or Node.Right=nil
|
||||
begin
|
||||
// for descendants to override
|
||||
end;
|
||||
|
||||
procedure TAvgLvlTree.BalanceAfterInsert(ANode: TAvgLvlTreeNode);
|
||||
var
|
||||
OldParent, OldRight, OldLeft: TAvgLvlTreeNode;
|
||||
@ -1080,65 +1093,17 @@ end;
|
||||
|
||||
procedure TAvgLvlTree.Delete(ANode: TAvgLvlTreeNode);
|
||||
var
|
||||
OldParent, OldLeft, OldRight, Successor, OldSuccParent, OldSuccLeft,
|
||||
OldSuccRight: TAvgLvlTreeNode;
|
||||
OldBalance: integer;
|
||||
OldParent: TAvgLvlTreeNode;
|
||||
Child: TAvgLvlTreeNode;
|
||||
begin
|
||||
while (ANode.Left<>nil) and (ANode.Right<>nil) do begin
|
||||
if (ANode.Left<>nil) and (ANode.Right<>nil) then begin
|
||||
// ANode has both: Left and Right
|
||||
// Switch ANode position with Successor
|
||||
// Because ANode.Right<>nil the Successor is a child of ANode
|
||||
Successor:=ANode.FindSuccessor;
|
||||
|
||||
OldBalance:=ANode.Balance;
|
||||
ANode.Balance:=Successor.Balance;
|
||||
Successor.Balance:=OldBalance;
|
||||
|
||||
OldParent:=ANode.Parent;
|
||||
OldLeft:=ANode.Left;
|
||||
OldRight:=ANode.Right;
|
||||
OldSuccParent:=Successor.Parent;
|
||||
OldSuccLeft:=Successor.Left;
|
||||
OldSuccRight:=Successor.Right;
|
||||
|
||||
if OldParent<>nil then begin
|
||||
if OldParent.Left=ANode then
|
||||
OldParent.Left:=Successor
|
||||
else
|
||||
OldParent.Right:=Successor;
|
||||
end else
|
||||
fRoot:=Successor;
|
||||
Successor.Parent:=OldParent;
|
||||
|
||||
if OldSuccParent<>ANode then begin
|
||||
if OldSuccParent.Left=Successor then
|
||||
OldSuccParent.Left:=ANode
|
||||
else
|
||||
OldSuccParent.Right:=ANode;
|
||||
Successor.Right:=OldRight;
|
||||
ANode.Parent:=OldSuccParent;
|
||||
if OldRight<>nil then
|
||||
OldRight.Parent:=Successor;
|
||||
end else begin
|
||||
{ ANode Successor
|
||||
\ => \
|
||||
Successor ANode }
|
||||
Successor.Right:=ANode;
|
||||
ANode.Parent:=Successor;
|
||||
end;
|
||||
|
||||
ANode.Left:=OldSuccLeft;
|
||||
if OldSuccLeft<>nil then
|
||||
OldSuccLeft.Parent:=ANode;
|
||||
ANode.Right:=OldSuccRight;
|
||||
if OldSuccRight<>nil then
|
||||
OldSuccRight.Parent:=ANode;
|
||||
Successor.Left:=OldLeft;
|
||||
if OldLeft<>nil then
|
||||
OldLeft.Parent:=Successor;
|
||||
SwitchPositionWithSuccessor(ANode,ANode.Successor);
|
||||
end;
|
||||
// left or right is nil
|
||||
DeletingNode(aNode);
|
||||
OldParent:=ANode.Parent;
|
||||
ANode.Parent:=nil;
|
||||
if ANode.Left<>nil then
|
||||
@ -1160,7 +1125,7 @@ begin
|
||||
end;
|
||||
BalanceAfterDelete(OldParent);
|
||||
end else begin
|
||||
// Node is the only node of tree
|
||||
// Node was Root
|
||||
fRoot:=Child;
|
||||
end;
|
||||
dec(FCount);
|
||||
@ -1274,7 +1239,7 @@ begin
|
||||
Data:=ANode.Data;
|
||||
Result:=ANode;
|
||||
repeat
|
||||
LeftNode:=Result.FindPrecessor;
|
||||
LeftNode:=Result.Precessor;
|
||||
if (LeftNode=nil) or (Compare(Data,LeftNode.Data)<>0) then break;
|
||||
Result:=LeftNode;
|
||||
until false;
|
||||
@ -1292,7 +1257,7 @@ begin
|
||||
Data:=ANode.Data;
|
||||
Result:=ANode;
|
||||
repeat
|
||||
RightNode:=Result.FindSuccessor;
|
||||
RightNode:=Result.Successor;
|
||||
if (RightNode=nil) or (Compare(Data,RightNode.Data)<>0) then break;
|
||||
Result:=RightNode;
|
||||
until false;
|
||||
@ -1328,7 +1293,7 @@ begin
|
||||
Result:=FindLeftMost(Data);
|
||||
while (Result<>nil) do begin
|
||||
if Result.Data=Data then break;
|
||||
Result:=Result.FindSuccessor;
|
||||
Result:=Result.Successor;
|
||||
if Result=nil then exit(nil);
|
||||
if Compare(Data,Result.Data)<>0 then exit(nil);
|
||||
end;
|
||||
@ -1340,7 +1305,7 @@ var
|
||||
begin
|
||||
Result:=Find(Data);
|
||||
while (Result<>nil) do begin
|
||||
Left:=Result.FindPrecessor;
|
||||
Left:=Result.Precessor;
|
||||
if (Left=nil) or (Compare(Data,Left.Data)<>0) then break;
|
||||
Result:=Left;
|
||||
end;
|
||||
@ -1352,7 +1317,7 @@ var
|
||||
begin
|
||||
Result:=Find(Data);
|
||||
while (Result<>nil) do begin
|
||||
Right:=Result.FindSuccessor;
|
||||
Right:=Result.Successor;
|
||||
if (Right=nil) or (Compare(Data,Right.Data)<>0) then break;
|
||||
Result:=Right;
|
||||
end;
|
||||
@ -1381,7 +1346,7 @@ end;
|
||||
function TAvgLvlTree.FindSuccessor(ANode: TAvgLvlTreeNode): TAvgLvlTreeNode;
|
||||
begin
|
||||
if ANode<>nil then
|
||||
Result:=ANode.FindSuccessor
|
||||
Result:=ANode.Successor
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
@ -1389,7 +1354,7 @@ end;
|
||||
function TAvgLvlTree.FindPrecessor(ANode: TAvgLvlTreeNode): TAvgLvlTreeNode;
|
||||
begin
|
||||
if ANode<>nil then
|
||||
Result:=ANode.FindPrecessor
|
||||
Result:=ANode.Precessor
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
@ -1401,7 +1366,7 @@ begin
|
||||
if ANode=nil then exit;
|
||||
LeftMost:=ANode;
|
||||
repeat
|
||||
PreNode:=LeftMost.FindPrecessor;
|
||||
PreNode:=LeftMost.Precessor;
|
||||
if (PreNode=nil) or (Compare(ANode,PreNode)<>0) then break;
|
||||
LeftMost:=PreNode;
|
||||
until false;
|
||||
@ -1419,7 +1384,7 @@ begin
|
||||
if ANode=nil then exit;
|
||||
RightMost:=ANode;
|
||||
repeat
|
||||
PostNode:=RightMost.FindSuccessor;
|
||||
PostNode:=RightMost.Successor;
|
||||
if (PostNode=nil) or (Compare(ANode,PostNode)<>0) then break;
|
||||
RightMost:=PostNode;
|
||||
until false;
|
||||
@ -1519,8 +1484,7 @@ procedure TAvgLvlTree.WriteReportToStream(s: TStream);
|
||||
WasLeft:=IsLeft;
|
||||
AParent:=AParent.Parent;
|
||||
end;
|
||||
b+=Format('%p Self=%p Parent=%p Balance=%d'+LineEnding, [
|
||||
ANode.Data, Pointer(ANode),Pointer(ANode.Parent), ANode.Balance]);
|
||||
b+=NodeToReportStr(ANode)+LineEnding;
|
||||
WriteStr(b);
|
||||
WriteTreeNode(ANode.Left);
|
||||
end;
|
||||
@ -1532,6 +1496,12 @@ begin
|
||||
WriteStr('-End-Of-AVL-Tree---------------------'+LineEnding);
|
||||
end;
|
||||
|
||||
function TAvgLvlTree.NodeToReportStr(aNode: TAvgLvlTreeNode): string;
|
||||
begin
|
||||
Result:=Format('%p Self=%p Parent=%p Balance=%d',
|
||||
[aNode.Data, Pointer(aNode),Pointer(aNode.Parent), aNode.Balance]);
|
||||
end;
|
||||
|
||||
function TAvgLvlTree.ReportAsString: string;
|
||||
var ms: TMemoryStream;
|
||||
begin
|
||||
@ -1582,7 +1552,7 @@ begin
|
||||
while ANode<>nil do begin
|
||||
List[i]:=ANode.Data;
|
||||
inc(i);
|
||||
ANode:=ANode.FindSuccessor;
|
||||
ANode:=ANode.Successor;
|
||||
end;
|
||||
// clear the tree
|
||||
Clear;
|
||||
@ -1605,8 +1575,7 @@ procedure TAvgLvlTree.RotateLeft(aNode: TAvgLvlTreeNode);
|
||||
/ \ /
|
||||
Left OldRight Node
|
||||
/ / \
|
||||
OldRightLeft Left OldRightLeft
|
||||
}
|
||||
OldRightLeft Left OldRightLeft }
|
||||
var
|
||||
OldRight: TAvgLvlTreeNode;
|
||||
AParent: TAvgLvlTreeNode;
|
||||
@ -1637,8 +1606,7 @@ procedure TAvgLvlTree.RotateRight(aNode: TAvgLvlTreeNode);
|
||||
/ \ \
|
||||
OldLeft Right Node
|
||||
\ / \
|
||||
OldLeftRight OldLeftRight Right
|
||||
}
|
||||
OldLeftRight OldLeftRight Right }
|
||||
var
|
||||
OldLeft: TAvgLvlTreeNode;
|
||||
AParent: TAvgLvlTreeNode;
|
||||
@ -1662,11 +1630,78 @@ begin
|
||||
OldLeft.Right:=aNode;
|
||||
end;
|
||||
|
||||
procedure TAvgLvlTree.SwitchPositionWithSuccessor(aNode,
|
||||
aSuccessor: TAvgLvlTreeNode);
|
||||
{ called by delete, when aNode.Left<>nil and aNode.Right<>nil
|
||||
Switch ANode position with Successor
|
||||
Because ANode.Right<>nil the Successor is a child of ANode }
|
||||
var
|
||||
OldBalance: Integer;
|
||||
OldParent: TAvgLvlTreeNode;
|
||||
OldLeft: TAvgLvlTreeNode;
|
||||
OldRight: TAvgLvlTreeNode;
|
||||
OldSuccParent: TAvgLvlTreeNode;
|
||||
OldSuccLeft: TAvgLvlTreeNode;
|
||||
OldSuccRight: TAvgLvlTreeNode;
|
||||
begin
|
||||
OldBalance:=aNode.Balance;
|
||||
aNode.Balance:=aSuccessor.Balance;
|
||||
aSuccessor.Balance:=OldBalance;
|
||||
|
||||
OldParent:=aNode.Parent;
|
||||
OldLeft:=aNode.Left;
|
||||
OldRight:=aNode.Right;
|
||||
OldSuccParent:=aSuccessor.Parent;
|
||||
OldSuccLeft:=aSuccessor.Left;
|
||||
OldSuccRight:=aSuccessor.Right;
|
||||
|
||||
if OldParent<>nil then begin
|
||||
if OldParent.Left=aNode then
|
||||
OldParent.Left:=aSuccessor
|
||||
else
|
||||
OldParent.Right:=aSuccessor;
|
||||
end else
|
||||
fRoot:=aSuccessor;
|
||||
aSuccessor.Parent:=OldParent;
|
||||
|
||||
if OldSuccParent<>aNode then begin
|
||||
if OldSuccParent.Left=aSuccessor then
|
||||
OldSuccParent.Left:=aNode
|
||||
else
|
||||
OldSuccParent.Right:=aNode;
|
||||
aSuccessor.Right:=OldRight;
|
||||
aNode.Parent:=OldSuccParent;
|
||||
if OldRight<>nil then
|
||||
OldRight.Parent:=aSuccessor;
|
||||
end else begin
|
||||
{ aNode aSuccessor
|
||||
\ => \
|
||||
aSuccessor aNode }
|
||||
aSuccessor.Right:=aNode;
|
||||
aNode.Parent:=aSuccessor;
|
||||
end;
|
||||
|
||||
aNode.Left:=OldSuccLeft;
|
||||
if OldSuccLeft<>nil then
|
||||
OldSuccLeft.Parent:=aNode;
|
||||
aNode.Right:=OldSuccRight;
|
||||
if OldSuccRight<>nil then
|
||||
OldSuccRight.Parent:=aNode;
|
||||
aSuccessor.Left:=OldLeft;
|
||||
if OldLeft<>nil then
|
||||
OldLeft.Parent:=aSuccessor;
|
||||
end;
|
||||
|
||||
procedure TAvgLvlTree.Init;
|
||||
begin
|
||||
FNodeClass:=TAvgLvlTreeNode;
|
||||
end;
|
||||
|
||||
procedure TAvgLvlTree.NodeAdded(aNode: TAvgLvlTreeNode);
|
||||
begin
|
||||
// for descendants to override
|
||||
end;
|
||||
|
||||
function TAvgLvlTree.Compare(Data1, Data2: Pointer): integer;
|
||||
begin
|
||||
if Assigned(FOnCompare) then
|
||||
@ -1675,7 +1710,6 @@ begin
|
||||
Result:=FOnObjectCompare(Self,Data1,Data2);
|
||||
end;
|
||||
|
||||
|
||||
{ TAvgLvlTreeNode }
|
||||
|
||||
function TAvgLvlTreeNode.TreeDepth: integer;
|
||||
@ -1743,7 +1777,7 @@ begin
|
||||
if Right<>nil then inc(Result,Right.GetCount);
|
||||
end;
|
||||
|
||||
function TAvgLvlTreeNode.FindSuccessor: TAvgLvlTreeNode;
|
||||
function TAvgLvlTreeNode.Successor: TAvgLvlTreeNode;
|
||||
begin
|
||||
Result:=Right;
|
||||
if Result<>nil then begin
|
||||
@ -1756,7 +1790,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TAvgLvlTreeNode.FindPrecessor: TAvgLvlTreeNode;
|
||||
function TAvgLvlTreeNode.Precessor: TAvgLvlTreeNode;
|
||||
begin
|
||||
Result:=Left;
|
||||
if Result<>nil then begin
|
||||
@ -2038,7 +2072,7 @@ begin
|
||||
while Node<>nil do begin
|
||||
Item:=PPointerToPointerItem(Node.Data);
|
||||
Dispose(Item);
|
||||
Node:=Node.FindSuccessor;
|
||||
Node:=Node.Successor;
|
||||
end;
|
||||
FItems.Clear;
|
||||
end;
|
||||
@ -2077,7 +2111,7 @@ var
|
||||
begin
|
||||
Node:=FindNode(Key);
|
||||
if Node<>nil then
|
||||
Node:=Node.FindSuccessor;
|
||||
Node:=Node.Successor;
|
||||
Result:=GetNode(Node,NextKey,NextValue);
|
||||
end;
|
||||
|
||||
@ -2088,7 +2122,7 @@ var
|
||||
begin
|
||||
Node:=FindNode(Key);
|
||||
if Node<>nil then
|
||||
Node:=Node.FindPrecessor;
|
||||
Node:=Node.Precessor;
|
||||
Result:=GetNode(Node,PrevKey,PrevValue);
|
||||
end;
|
||||
|
||||
@ -2104,7 +2138,7 @@ begin
|
||||
if FCurrent=nil then
|
||||
FCurrent:=FTree.FindLowest
|
||||
else
|
||||
FCurrent:=FCurrent.FindSuccessor;
|
||||
FCurrent:=FCurrent.Successor;
|
||||
Result:=FCurrent<>nil;
|
||||
end;
|
||||
|
||||
@ -2167,7 +2201,7 @@ begin
|
||||
Node:=FTree.FindLowest;
|
||||
while Node<>nil do begin
|
||||
DisposeItem(PStringMapItem(Node.Data));
|
||||
Node:=Node.FindSuccessor;
|
||||
Node:=Node.Successor;
|
||||
end;
|
||||
FTree.Clear;
|
||||
end;
|
||||
@ -2186,7 +2220,7 @@ begin
|
||||
while Node<>nil do begin
|
||||
Item:=PStringMapItem(Node.Data);
|
||||
List.Add(Item^.Name);
|
||||
Node:=Node.FindSuccessor;
|
||||
Node:=Node.Successor;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2225,8 +2259,8 @@ begin
|
||||
Item:=PStringMapItem(Node.Data);
|
||||
OtherItem:=PStringMapItem(OtherNode.Data);
|
||||
if not ItemsAreEqual(Item,OtherItem) then exit;
|
||||
OtherNode:=OtherNode.FindSuccessor;
|
||||
Node:=Node.FindSuccessor;
|
||||
OtherNode:=OtherNode.Successor;
|
||||
Node:=Node.Successor;
|
||||
end;
|
||||
if OtherNode<>nil then exit;
|
||||
Result:=true;
|
||||
@ -2244,7 +2278,7 @@ begin
|
||||
while SrcNode<>nil do begin
|
||||
SrcItem:=PStringMapItem(SrcNode.Data);
|
||||
Tree.Add(CreateCopy(SrcItem));
|
||||
SrcNode:=SrcNode.FindSuccessor;
|
||||
SrcNode:=SrcNode.Successor;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user