unit Freya.DataStructures.Trees;
public
BinaryTree = class[X: IComparable]
// El tipo paramétrico debe soportar la interfaz IComparable
protected
// Esta clase anidada terminará de declararse más adelante
TreeNode = class[X: IComparable];
Root: TreeNode of X;
public
procedure Add(Value: X);
ensures Contains(Value);
function Contains(AValue: X): Boolean;
iterator Preorder: X;
end;
// Una clase anidada.
// Puede declararse fuera de la clase principal...
// ... para evitar la indentación excesiva.
BinaryTree.TreeNode = class[X: IComparable]
protected
function Contains(AValue: X): BinaryTree.TreeNode[X];
public
constructor TreeNode(AValue: X);
Value: X;
Left, Right: BinaryTree.TreeNode of X;
iterator Preorder: X;
end;
private // BinaryTree.TreeNode[X]
// No es necesario repetir el parámetro genérico formal, como en:
// constructor BinaryTree.TreeNode[X](AValue: X);
// function BinaryTree.TreeNode[X].Contains(AValue: X): TTreeNode[X];
constructor BinaryTree.TreeNode(AValue: X);
// BinaryTree.TreeNode es el nombre de la clase anidada,
// en vez de un par clase.constructor.
// Los constructores de Freya son anónimos
begin
Value := AValue;
end;
function BinaryTree.TreeNode.Contains(AValue: X): TreeNode[X];
begin
if AValue = Value then
Result := Self
else
begin
Result := nil;
if AValue < Value then
begin
if Left <> nil then
Result := Left.Contains(AValue);
end
else if Right <> nil then
Result := Right.Contains(AValue);
end;
end;
iterator BinaryTree.TreeNode.Preorder: X;
begin
Result := Value;
Yield;
if Left <> nil then
for Result in Left.Preorder do Yield;
if Right <> nil then
for Result in Right.Preorder do Yield;
end;
private // BinaryTree[X]
function BinaryTree.Contains(AValue: X): Boolean;
begin
Result := (Root <> nil) and (Root.Contains(AValue) <> nil);
end;
procedure BinaryTree.Add(AValue: X);
var
Parent, Current: TreeNode[X];
begin
Parent := nil;
Current := Root;
while (Current <> nil) and (Current.Value <> AValue) do
begin
Parent := Current;
if AValue < Current.Value then
Current := Current.Left
else
Current := Current.Right;
end;
if Current = nil then
begin
Current := new TreeNode[X](AValue);
if Parent = nil then
Root := Current
else if AValue < Parent.Value then
Parent.Left := Current
else
Parent.Right := Current;
end;
end;
iterator BinaryTree.Preorder: X;
begin
if Root <> nil then
for Result in Root.Preorder do
Yield;
end;
end.