随笔 - 809  文章 - 0 评论 - 144 阅读 - 770万

在 Delphi 中,创建一个泛型链表(LinkedList)容器需要定义节点类和链表管理类,并确保它们都是泛型的,以便可以存储任何类型的元素。以下是一个简单的泛型链表实现,它包括节点类 TLinkedListNode<T> 和链表管理类 TLinkedList<T>。这个实现支持从中间删除元素。

unit Generic.LinkedList;

interface

uses
  System.SysUtils, System.Generics.Collections;

type
  // 节点类,泛型 T 表示节点存储的数据类型
  TLinkedListNode<T> = class
  private
    FData: T;
    FNext: TLinkedListNode<T>;
  public
    constructor Create(const AData: T);
    property Data: T read FData write FData;
    property Next: TLinkedListNode<T> read FNext write FNext;
  end;

  // 链表类,泛型 T 表示链表存储的数据类型
  TLinkedList<T> = class
  private
    FHead: TLinkedListNode<T>;
    FTail: TLinkedListNode<T>;
    FCount: Integer;
    function GetNodeAt(AIndex: Integer): TLinkedListNode<T>;
  public
    constructor Create;
    destructor Destroy; override;
    
    // 添加元素到链表末尾
    procedure Add(const AData: T);
    
    // 从链表中删除指定索引处的元素
    procedure Delete(AIndex: Integer);
    
    // 获取链表中元素的数量
    function Count: Integer;
    
    // 获取或设置指定索引处的元素
    property Items[AIndex: Integer]: T read GetNodeAt.Data write GetNodeAt.Data; default;
  end;

implementation

{ TLinkedListNode<T> }

constructor TLinkedListNode<T>.Create(const AData: T);
begin
  FData := AData;
  FNext := nil;
end;

{ TLinkedList<T> }

constructor TLinkedList<T>.Create;
begin
  FHead := nil;
  FTail := nil;
  FCount := 0;
end;

destructor TLinkedList<T>.Destroy;
var
  Current, Temp: TLinkedListNode<T>;
begin
  Current := FHead;
  while Current <> nil do
  begin
    Temp := Current;
    Current := Current.Next;
    Temp.Free;
  end;
  inherited;
end;

procedure TLinkedList<T>.Add(const AData: T);
var
  NewNode: TLinkedListNode<T>;
begin
  NewNode := TLinkedListNode<T>.Create(AData);
  if FTail <> nil then
  begin
    FTail.Next := NewNode;
  end
  else
  begin
    FHead := NewNode;
  end;
  FTail := NewNode;
  Inc(FCount);
end;

procedure TLinkedList<T>.Delete(AIndex: Integer);
var
  Current, Previous: TLinkedListNode<T>;
begin
  if (AIndex < 0) or (AIndex >= FCount) then
    raise Exception.Create('Index out of bounds');

  Current := FHead;
  if AIndex = 0 then
  begin
    FHead := Current.Next;
    if FHead = nil then
      FTail := nil;
    Current.Free;
  end
  else
  begin
    Previous := nil;
    while AIndex > 0 do
    begin
      Previous := Current;
      Current := Current.Next;
      Dec(AIndex);
    end;
    Previous.Next := Current.Next;
    if Previous.Next = nil then
      FTail := Previous;
    Current.Free;
  end;
  Dec(FCount);
end;

function TLinkedList<T>.Count: Integer;
begin
  Result := FCount;
end;

function TLinkedList<T>.GetNodeAt(AIndex: Integer): TLinkedListNode<T>;
var
  Current: TLinkedListNode<T>;
  I: Integer;
begin
  if (AIndex < 0) or (AIndex >= FCount) then
    raise Exception.Create('Index out of bounds');

  Current := FHead;
  for I := 0 to AIndex - 1 do
  begin
    Current := Current.Next;
  end;
  Result := Current;
end;

end.

这个实现包括了以下功能:

  • TLinkedListNode<T>:表示链表中的一个节点,包含数据和指向下一个节点的指针。
  • TLinkedList<T>:表示链表本身,管理节点的添加、删除和访问。
  • Add 方法:在链表末尾添加一个新元素。
  • Delete 方法:从链表中删除指定索引处的元素。如果索引是 0,则删除头节点;否则,遍历链表找到要删除的节点,并调整前一个节点的 Next 指针。
  • Count 方法:返回链表中元素的数量。
  • Items 属性:允许通过索引访问链表中的元素。这是通过 GetNodeAt 方法实现的,该方法根据索引返回对应的节点。

请注意,这个实现没有处理并发访问或线程安全问题。如果你需要在多线程环境中使用链表,请添加适当的同步机制。此外,这个链表是单向的,如果你需要双向链表,可以相应地扩展节点类和链表类。

posted on   del88  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示