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

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

代码实例:

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);

 

 

 

 

 

 

//t9步:切换到结点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;

 

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

原代码如下:

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

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.

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
MFC TreeControl 是 MFC 框架提供的一个用于显示层次结构数据的控件。它通常用于展示形目录或者状数据结构。 MFC TreeControl 的源码是由 Microsoft 提供的,基于 C++ 编写。它主要包含了一系列的和函数,用于实现形控件的各种功能,比如绘制节点、添加、删除、展开、折叠节点等操作。 源码中的主要包括 CTreeCtrl、CTreeView、CTreeCtrlEx 等。其中,CTreeCtrl 是 MFC 框架提供的基本形控件,CTreeView 是 CTreeCtrl 的一个扩展,CTreeCtrlEx 则是对 CTreeCtrl 进一步封装提供了更多的功能。 通过阅读源码,我们可以了解到 MFC TreeControl 是如何处理节点的数据存储、绘制和交互的。可以通过重写相关的回调函数来改变节点的外观和行为,比如绘制节点图标和文本、设置节点是否可展开等。 在源码中还会看到一些使用消息机制来处理用户输入和控件的事件响应,比如点击节点、拖拽节点等。通过这些消息机制,我们可以自定义一些特定的处理逻辑。 除了基本的功能,源码中还可能包含了一些辅助和工具函数,用于提供方便的操作和扩展功能。比如节点的排序、查找操作,以及一些自定义的节点等。 总结起来,MFC TreeControl 的源码是一个构建形控件的基础框架,通过理解和使用它,我们可以方便地实现状数据的展示和管理,并根据需要进行自定义扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值