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.
本文來自博客園,作者:del88,轉載請注明原文鏈接:http://www.rzrgm.cn/del88/p/18607788
浙公網安備 33010602011771號