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

unit zx.core.FixedQueue;

interface

uses
  System.SysUtils, System.Generics.Collections;

type

  TFixedQueue<T> = class
  private
    /// <summary>
    /// 一个动态数组,用于存储队列元素,动态数组会自动管理内存
    /// </summary>
    FItems: TArray<T>;

    /// <summary>
    /// 头指针,指向队列的逻辑第一个元素
    /// </summary>
    FFront: Integer;

    /// <summary>
    /// 尾指针,指向队列的逻辑最后一个元素
    /// </summary>
    FRear: Integer;

    /// <summary>
    /// 当前队列中的元素数量
    /// </summary>
    FCount: Integer;

    /// <summary>
    /// 队列的固定容量
    /// </summary>
    FCapacity: Integer;

    /// <summary>
    /// 根据逻辑索引获取元素
    /// </summary>
    function GetItem(Index: Integer): T;

    /// <summary>
    /// 根据逻辑索引设置元素
    /// </summary>
    procedure SetItem(Index: Integer; const Value: T);

    /// <summary>
    /// 效仿官方的 TQueue
    /// </summary>
    function GetIsEmpty: Boolean; inline;
    function GetIsFull: Boolean; inline;
  public
    constructor Create(Capacity: Integer);

    procedure Enqueue(Item: T);
    function Dequeue: T;
    function Peek: T;

    property Count: Integer read FCount;
    property Capacity: Integer read FCapacity;

    property IsEmpty: Boolean read GetIsEmpty;
    property IsFull: Boolean read GetIsFull;

    /// <summary>
    /// 可以根据这个来遍历,注意 Index 其实是逻辑索引
    /// for var i = 0 to count - 1 ... item[i] 就遍历了
    /// </summary>
    property Items[Index: Integer]: T read GetItem write SetItem;
  end;

implementation

constructor TFixedQueue<T>.Create(Capacity: Integer);
begin
  if Capacity <= 0 then
    raise EArgumentOutOfRangeException.Create('容量必须大于0!');

  FCapacity := Capacity;
  SetLength(FItems, FCapacity);
  FFront := 0;
  FRear := -1;
  FCount := 0;
end;

procedure TFixedQueue<T>.Enqueue(Item: T);
begin
  if FCount = FCapacity then
    raise Exception.Create('队列已满,新入队失败!');

  FRear := (FRear + 1) mod FCapacity;
  FItems[FRear] := Item;
  Inc(FCount);
end;

function TFixedQueue<T>.Dequeue: T;
begin
  if FCount = 0 then
    raise Exception.Create('队列是空,无法出队!');

  Result := FItems[FFront];
  FFront := (FFront + 1) mod FCapacity;
  Dec(FCount);
end;

function TFixedQueue<T>.Peek: T;
begin
  if FCount = 0 then
    raise Exception.Create('队列是空,无法 Peek!');

  Result := FItems[FFront];
end;

function TFixedQueue<T>.GetItem(Index: Integer): T;
begin
  if (Index < 0) or (Index >= FCount) then
    raise EArgumentOutOfRangeException.Create('队列索引越界!');

  Result := FItems[(FFront + Index) mod FCapacity];
end;

procedure TFixedQueue<T>.SetItem(Index: Integer; const Value: T);
begin
  if (Index < 0) or (Index >= FCount) then
    raise EArgumentOutOfRangeException.Create('队列索引越界!');

  FItems[(FFront + Index) mod FCapacity] := Value;
end;

function TFixedQueue<T>.GetIsEmpty: Boolean;
begin
  Result := FCount = 0;
end;

function TFixedQueue<T>.GetIsFull: Boolean;
begin
  Result := FCount = FCapacity;
end;

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