Delphi实现链表

      在本文中,我把对链表的操作封装到一个类中,此类是单向链表,如果想做成双向列表,需要在PNode里面加入一个Pre,

指向当前指针的前一项;如果是环形链表,则需要将尾节点的Next指向头节点。原理都是类似的。一下是这个类的详细代码。

供大家参考。(DelphiXe2中实现的)

unit Unit2;

interface
uses
  Winapi.Windows,System.SysUtils, System.Classes,Vcl.Forms;

type
  TStudent=record
    id : Integer;
    StudNo : string;
    StuName : string;
    Age : Integer;
    Sex : string;
  end;
  PStudent = ^TStudent;

  PNode=^TNode;
  TNode=record
    Next : PNode;     //下一个节点,如果需要双向链表,在这里加一个 Pre : PNode
    data : PStudent;  //数据项,也可以直接用字段来表示,这里用指针来实现
  end;

  TMyLinkList= class
  private
    FHeadNode : PNode;
    FCurrNode : PNode;
    FCount : Integer;
    function AnalysisData(AData : string) : PNode; //解析文本数据
  public
    function Add(Node : PNode) : Boolean;
    function Delete(Node : PNode) : Boolean;
    function SearchNode(id : Integer) : PNode;
    function GetAllNode : TList;
    function GetHead: PNode;
    function GetCurrNode: PNode;
    function GetSize : Integer;
    function SaveData : Boolean;  //把链表数据保存为文本文件
    function LoadData : Boolean; //从文本中加载链表数据
    function Next : PNode;
    function First : PNode;
    constructor Create;
    destructor Destroy; override; {析构方法}
end;
implementation

{ TMyLinkList }

constructor TMyLinkList.Create;
begin
  inherited;
  FHeadNode := nil;
  FCurrNode := nil;
  FCount := 0;
end;

destructor TMyLinkList.Destroy;
var
  mList : TList;
  i : Integer;
  Node : PNode;
  stu : PStudent;
begin
  mList := GetAllNode;
  for i := 0 to mList.Count-1 do
  begin
    Node := PNode(mList[i]);
    stu := Node.data;
    Dispose(stu);
    Dispose(Node);
  end;
  mList.Clear;
  mList.Free;
  inherited;
end;

//新增节点,需要将下一个节点指向Nil

function TMyLinkList.Add(Node: PNode): Boolean;
begin
  Inc(FCount);
  if not Assigned(FHeadNode) then
  begin
    FHeadNode := Node;
    FCurrNode := Node;
    FCurrNode.Next := nil;
  end else begin
    FCurrNode.Next := Node;
    FCurrNode := Node;
    FCurrNode.Next := nil;
  end;
end;

//删除节点,需要将当前节点的上一个节点找出来,然后指向当前节点的下一个节点,接着删除当前节点

function TMyLinkList.Delete(Node: PNode): Boolean;
var
  i : Integer;
  ANode,ADestNode : PNode;
begin
  ANode := FHeadNode;
  ADestNode := Node.Next;
  for I := 1 to FCount do
  begin
    if ANode.Next = Node then
    begin
      Break;
    end else begin
      ANode := ANode.Next;
    end;
  end;
  ANode.Next := ADestNode;
  Dispose(Node);
  FCount := FCount - 1;
end;

//查找节点,根据数据的主键来查找

function TMyLinkList.SearchNode(id: Integer): PNode;
var
  ANode : PNode;
  i : Integer;
  mList : TList;
begin
  Result := nil;
  ANode := FHeadNode;
  for I := 1 to FCount do
  begin
    if ANode.data.id = id then
    begin
      Result := ANode;
      Break;
    end;
    ANode := ANode.Next;
  end;
end;

//查询所有节点,并将节点数据装载到List里面去,此方法并非链表所必须的方法

function TMyLinkList.GetAllNode : TList;
var
  i : Integer;
  mList : TList;
  ANode : PNode;
begin
  ANode := FHeadNode;
  mList := TList.Create;
  for I := 1 to FCount do
  begin
    mList.Add(ANode);
    ANode := ANode.Next;
  end;
  Result := mList;
end;

function TMyLinkList.GetCurrNode: PNode;
begin
  Result := FCurrNode;
end;

function TMyLinkList.GetHead: PNode;
begin
  Result := FHeadNode;
end;

function TMyLinkList.GetSize: Integer;
begin
  Result := FCount;
end;

//获取头节点

function TMyLinkList.First: PNode;
begin
  Result := nil;
  if FCount=0 then Exit;
  FCurrNode := FHeadNode;
  Result := FCurrNode;
end;

//获取下一个节点

function TMyLinkList.Next: PNode;
begin
  Result := nil;
  if FCount=0 then Exit;
  if FCurrNode.Next = nil then Exit;
  FCurrNode := FCurrNode.Next;
  Result := FCurrNode;
end;

function TMyLinkList.SaveData: Boolean;
var
  mList : TList;
  i : Integer;
  ANode : PNode;
  dataList : TStringList;
  sText,sFileName : string;
begin
  try
    sFileName := ExtractFilePath(Application.ExeName) + 'Linklist.data';
    dataList := TStringList.Create;
    mList := GetAllNode;
    for i := 0 to mList.Count-1 do
    begin
      ANode := PNode(mList[i]);
      sText := Format('id=%d,StudNo=%s,StuName=%s,Age=%d,Sex=%s',[ANode.data.id,ANode.data.StudNo,ANode.data.StuName,
        ANode.data.Age,ANode.data.Sex]);
      dataList.Add(sText);
    end;
    mList.Free;
    if FileExists(sFileName) then DeleteFile(sFileName);
    dataList.SaveToFile(sFileName);
  finally
    dataList.Free;
  end;
end;

function TMyLinkList.LoadData: Boolean;
var
  i : Integer;
  mList : TStringList;
  sFileName : string;
begin
  try
    sFileName := ExtractFilePath(Application.ExeName) + 'Linklist.data';
    mList := TStringList.Create;
    if not FileExists(sFileName) then Exit;
    mList.LoadFromFile(sFileName);
    for i := 0 to mList.Count-1 do
    begin
      Self.Add(AnalysisData(mList[i]));
    end;
  finally
    mList.Free;
  end;
end;

function TMyLinkList.AnalysisData(AData: string): PNode;
var
  i,j : Integer;
  mList : TStringList;
  sFileName : string;
  Node : PNode;
  Stu : PStudent;
begin
  try
    Result := nil;
    mList := TStringList.Create;
    mList.Delimiter := ',';
    mList.DelimitedText := AData;
    New(Node);
    New(Stu);
    Stu^.id := StrToInt(mList.Values['id']);
    Stu^.StudNo := mList.Values['StudNo'];
    Stu^.StuName := mList.Values['StuName'];
    Stu^.Sex := mList.Values['Sex'];
    Stu^.Age := StrToInt(mList.Values['Age']);
    Node.data := Stu;
    Result := Node;
  finally
    mList.Free;
  end;
end;

end.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值