自己编写树(Tree)的封装类

类别:Delphi 点击:0 评论:0 推荐:

在VCL中包含有一个TList类,几乎可以实现<链表>所有功能,Delphi的工程师真是伟大。但是在实际应用中需要TTree类,来实现<树>的功能,我写了两个类TyuTree,TYuNode。可以方便实现,树创建,结点增删、移动功能。请大家指教。

代码实例:

Procedure Test();

Var

 YuTree: TyuTree;

  Node: TYuNode;

Begin  

  //第1步:创建树、增加第一个结点0

YuTree := TYuTree.Create;

Node := YuTree.Add(nil);//nil,表示增加根结点

Node.Data := Pointer(0);

 

 

 

 

//第2步:在结点0下增加子结点1

Node := YuTree.AddChild(Node);Node指向结点0

Node.Data := Pointer(1);

 

 

 

 

 

 

//第3步:在结点1下增加子结点2

Node := YuTree.AddChild(Node);

Node.Data := Pointer(2);

 

 

 

 

 

 

//第4步:切换到结点2的父结点1

Node := Node.GetParent;

 

 

 

 

 

 

 

 

//第5步:在结点1下增加子结点3,并作为第1个子结点

Node := YuTree.AddChildFirst(Node);

Node.Data := Pointer(3);

 

 

 

 

 

 

//第6步:切换到结点3的父结点1

Node := Node.GetParent;

 

 

 

 

 

 

//第7步:增加结点1下子结点4,作为最后一个子结点

Node := YuTree.AddChild (Node);

Node.Data := Pointer(4);

 

 

 

 

 

//第8步:增加结点4的兄弟结点5,作为第一个兄弟结点

Node := YuTree.AddFirst(Node);

Node.Data := Pointer(5);

 

 

 

 

 

 

//t第9步:切换到结点5的下一个兄弟结点3

Node := Node.GetNextBrother;

 

 

 

 

 

 

 

 

//第10步:在结点3下插入一个兄弟结点6

Node := YuTree.Add(Node);

Node.Data := Pointer(6 );

 

 

 

 

 

 

//第11步:删除结点6

Node.Delete; //或YuTree.Delete(Node);

 

 

 

 

 

//其它用法

  //结点2.GetNextBrother() = 结点4        返回该结点的下一个兄弟

  //结点2.GetPrevBrother() = 结点3      返回该结点的上一个兄弟

  //结点1.GetFirstChild() = 结点5;       返回该结点的第一个子结点

  //结点1.GetLastChild() = 结点4         返回该结点的最后一个子结点

 

  //结点1.GetNext = 结点5

  //结点1.GetPrev = 结点0

  //结点2.GetFirstBrother() = 结点5        返回该结点的第一个兄弟

//结点2.GetLastBrother() = 结点4         返回该结点最后一个兄弟

 

//YuTree.FirstNode = 结点0

//YuTree.Clear(); 清空所有结点

End;

 

说明:该在程序中是以二叉树来表示的,FDownLeft,FDownRight分别表示二叉树的左指针、右指针。

原代码如下:

//――――――开始―――――――――――――――――――――――――――-

unit uYuTree;

 

interface

 

type

  TYuNodeAttachMode = (ynaAdd, ynaAddFirst, ynaAddChild, ynaAddChildFirst, ynaInsert);

  TYuTree = class;

  TYuNode = class(TObject)

  private

    //Self.Tree中除Root外, FUpLeft, FUpRight有且只有一个为空 

    FUpLeft: TYuNode;     //Self.FUpLeft.FDownLeft = Self (该指针指向的结点是该结点的父结点)

    FUpRight: TYuNode;    //Self.FUpRight.FDownRight = Self (该指针指向的结点是该结点的上一个兄弟)

 

    FDownLeft: TYuNode;   //二叉树的左指针,表树的子结点

    FDownRight: TYuNode;  //二叉树的右指针,表示树的下一个兄弟

    FOwner: TYuTree;

 

    //结点的状态信息

    FDeleting: Boolean;

    FIsRootOfDeleted: Boolean;

 

    function GetLevel(): Integer;

    function GetParent(): TYuNode;

 

    procedure CutFromTree();

 

  protected

    constructor Create(AOwner: TYuTree);

  public

    //Property Data: Pointer read FData write FData;

    Data: Pointer;

 

    //以下四个函数是基础函数,不调用其它函数,独立完成指定功能

    function GetNextBrother(): TYuNode;

    function GetPrevBrother(): TYuNode;

    function GetFirstChild(): TYuNode;

    function GetLastChild(): TYuNode;

 

    function GetNext: TYuNode;

    function GetPrev: TYuNode;

    function GetFirstBrother(): TYuNode;

    function GetLastBrother(): TYuNode;

 

    procedure MoveTo(Destination: TYuNode; Mode: TYuNodeAttachMode);

    procedure Delete();   

 

    property Level: Integer read GetLevel;

    property Parent: TYuNode read GetParent;

 

    destructor Destroy();override;

  end;

 

  TYuTree = class(TObject)

  private

    FFirstNode: TYuNode;

  public

    function Add(Brother: TYuNode):TYuNode;

    function AddFirst(Brother: TYuNode):TYuNode;

    function AddChild(Parent: TYuNode):TYuNode;

    function AddChildFirst(Parent: TYuNode):TYuNode;

    function Insert(Brother: TYuNode):TYuNode;

 

    procedure Clear();

    procedure Delete(Node: TYuNode);

 

    property FirstNode: TYuNode read FFirstNode;

 

    constructor Create();

    destructor Destroy();override;   

  end;

 

implementation

 

uses SysUtils, Math;

 

{ TYuNode }

 

constructor TYuNode.Create(AOwner: TYuTree);

begin

  if not Assigned(AOwner) then

    raise Exception.Create('AOwner is nil In TYuNode.Create');

 

  FOwner := AOwner;

  FUpLeft    := nil;

  FUpRight   := nil;

  FDownLeft  := nil;

  FDownRight := nil;

 

  FDeleting := False;

  FIsRootOfDeleted := False;

end;

 

destructor TYuNode.Destroy;

var

  SubNode, WillDeleteNode: TYuNode;

begin

  FDeleting := True;

 

  if FIsRootOfDeleted then //维护指针

    CutFromTree;

 

  SubNode := GetFirstChild;

  while SubNode <> nil do

  begin

    WillDeleteNode := SubNode;

    SubNode := SubNode.GetNextBrother;

    WillDeleteNode.Free;

  end;

 

  inherited;

end;

 

function TYuNode.GetFirstChild: TYuNode;

begin

  Result := FDownLeft;

end;

 

function TYuNode.GetFirstBrother: TYuNode;

begin

  Result := Self;

  while Result.GetPrevBrother <> nil do

    Result := Result.GetPrevBrother;

end;

 

function TYuNode.GetLastBrother: TYuNode;

begin

  Result := Self;

  while Result.GetNextBrother <> nil do

    Result := Result.GetNextBrother;

end;

 

function TYuNode.GetLastChild: TYuNode;

begin

  Result := FDownLeft;

  if Result = nil then Exit;

  while Result.FDownRight <> nil do

    Result := Result.FDownRight;

end;

 

function TYuNode.GetLevel: Integer;

var

  Node: TYuNode;

begin

  Node := Self;

  Result := -1;

  repeat

    Node := Node.Parent;

    Inc(Result);

  until Node = nil;

end;

 

function TYuNode.GetNext: TYuNode;

var

  Node: TYuNode;

begin

  //1.查看第一个子结点

  Result := GetFirstChild;

  //2.如果第1步不成功,查看下一个兄弟

  if Result = nil then

    Result := GetNextBrother;

 

  //3.如果第2步不成功,查看父结点的下一个兄弟

  //退出条件,成功找到(Result <> nil) 或 直到根结点仍没有找到(Node = nil)

  Node := Self.Parent;

  while (Result = nil) and (Node <> nil)  do

  begin

    Result := Node.GetNextBrother;

    Node := Node.Parent;

  end;

end;

 

function TYuNode.GetNextBrother: TYuNode;

begin

  Result := FDownRight;

end;

 

function TYuNode.GetParent: TYuNode;

begin

  Result := GetFirstBrother.FUpLeft;

end;

 

function TYuNode.GetPrev: TYuNode;

var

  Node: TYuNode;

begin

  //1.得到上一个兄弟

  Node := GetPrevBrother;

 

  //如果没有上一个兄弟,返回父结点

  if Node = nil then

  begin

    Result := Self.Parent;

    Exit;

  end;

 

  //否则,返回PrevBrother.GetLastChild.GetLastChild.........

  Result := Node;

  while Node <> nil do

  begin

    Result := Node;

    Node := Node.GetLastChild;

  end;

end;

 

function TYuNode.GetPrevBrother: TYuNode;

begin

  Result := FUpRight;

end;

 

procedure TYuNode.MoveTo(Destination: TYuNode; Mode: TYuNodeAttachMode);

var

  DestParent, AddNode: TYuNode;

begin

  if Destination = nil then

  begin

    Delete;

    Exit;

  end;

 

  if Destination.FOwner <> FOwner then

    raise Exception.CreateFmt('YuNode[@%d] Move To Another Tree In TYuNode.MoveTo', [Integer(@Self)]);

 

  DestParent := Destination.Parent;

  while DestParent <> nil do

  begin

    if DestParent = Self then

      raise Exception.CreateFmt('Destination Is YuNode[@%d]''s SubNode In TYuNode.MoveTo', [Integer(@Self)]);

    DestParent := DestParent.Parent;

  end;

 

  CutFromTree;

  case Mode of

    ynaAdd:           AddNode := FOwner.Add(Destination);

    ynaAddFirst:      AddNode := FOwner.AddFirst(Destination);

    ynaAddChild:      AddNode := FOwner.AddChild(Destination);

    ynaAddChildFirst: AddNode := FOwner.AddChildFirst(Destination);

    ynaInsert:        AddNode := FOwner.Insert(Destination);

  end;

 

  FUpLeft  := AddNode.FUpLeft;

  FUpRight := AddNode.FUpRight;

  FDownRight := AddNode.FDownRight;

 

  if FUpLeft <> nil then FUpLeft.FDownLeft := Self;

  if FUpRight <> nil then FUpRight.FDownRight := Self;

  if FDownRight <> nil then FDownRight.FUpRight := Self;

 

  AddNode.Free;

end;

 

procedure TYuNode.Delete;

begin

  if not FDeleting then

  begin

    FIsRootOfDeleted := True;

    Free;

  end;

end;

 

procedure TYuNode.CutFromTree;

begin

  if Self = FOwner.FFirstNode then

  begin

    FOwner.FFirstNode := GetNextBrother;

    if FOwner.FFirstNode <> nil then

      FOwner.FFirstNode.FUpRight := nil;

    Exit;

  end;

 

  if FDownRight <> nil then //有下一个兄弟

    if FUpRight <> nil then //有上一个兄弟

    begin

      FUpRight.FDownRight := FDownRight;

      FDownRight.FUpRight := FUpRight;

    end

    else                    //直接指向父结点

    begin

      FUpLeft.FDownLeft := FDownRight;

      FDownRight.FUpRight := nil;

      FDownRight.FUpLeft := FUpLeft;

    end

  else

    if FUpRight <> nil then //有上一个兄弟

      FUpRight.FDownRight := nil

    else                    //直接指向父结点

      FUpLeft.FDownLeft := nil;

end;

 

{ TYuTree }

 

function TYuTree.Add(Brother: TYuNode): TYuNode;

var

  Node: TYuNode;

begin

  if Brother = nil then

    if FFirstNode = nil then

    begin

      Result := TYuNode.Create(Self);

      FFirstNode := Result;

      Exit;

    end

    else

      Brother := FFirstNode;

 

  Node := Brother.GetLastBrother;

  Result := TYuNode.Create(Self);

  Node.FDownRight := Result;

  Result.FUpRight := Node;

end;

 

function TYuTree.AddChild(Parent: TYuNode): TYuNode;

var

  Node: TYuNode;

begin

  if Parent = nil then

  begin

    Result := Add(nil);

    Exit;

  end;

 

  Node := Parent.GetLastChild;

  Result := TYuNode.Create(Self);

 

  if Node = nil then

  begin

    Parent.FDownLeft := Result;

    Result.FUpLeft := Parent;

  end

  else

  begin

    Node.FDownRight := Result;

    Result.FUpRight := Node;

  end;

end;

 

function TYuTree.AddChildFirst(Parent: TYuNode): TYuNode;

var

  Node: TYuNode;

begin

  if Parent = nil then

  begin

    Result := Add(nil);

    Exit;

  end;

 

  Node := Parent.GetFirstChild;

  Result := TYuNode.Create(Self);

 

  if Node <> nil then

  begin

    Node.FUpLeft := nil;

    Node.FUpRight := Result;

  end;

 

  Result.FUpLeft := Parent;

  Result.FDownRight := Node;

 

  Parent.FDownLeft := Result;

end;

 

function TYuTree.AddFirst(Brother: TYuNode): TYuNode;

var

  Node, Parent: TYuNode;

begin

  if Brother = nil then

  begin

    Result := Add(nil);

    Exit;

  end;

 

  Node := Brother.GetFirstBrother;

  Parent := Node.Parent;

  Result := TYuNode.Create(Self);

 

  Node.FUpLeft := nil;

  Node.FUpRight := Result;

 

  Result.FUpLeft := Parent;

  Result.FDownRight := Node;

 

  if Parent <> nil then

    Parent.FDownLeft := Result

  else

    FFirstNode := Result;

end;

 

procedure TYuTree.Clear;

begin

  while FFirstNode <> nil do

    FFirstNode.Delete; 

end;

 

constructor TYuTree.Create;

begin

  FFirstNode := nil;

end;

 

procedure TYuTree.Delete(Node: TYuNode);

begin

  Node.Delete;

end;

 

destructor TYuTree.Destroy;

begin

  Clear;

  inherited;

end;

 

function TYuTree.Insert(Brother: TYuNode): TYuNode;

var

  Prev, Next: TYuNode;

begin

  if Brother = nil then

  begin

    Result := Add(nil);

    Exit;

  end;

 

  if Brother.GetNextBrother = nil then

    Result := Add(Brother)

  else

  begin

    Prev := Brother;

    Next := Brother.GetNextBrother;

    Result := TYuNode.Create(Self);

 

    Prev.FDownRight := Result;

    Next.FUpRight := Result;

 

    Result.FUpRight := Prev;

    Result.FDownRight := Next;

  end;

end;

 

end.

 

//――――――结束―――――――――――――――――――――――――――-

本文地址:http://com.8s8s.com/it/it4987.htm