sandque.pas

来自「模拟2维沙堆效果」· PAS 代码 · 共 134 行

PAS
134
字号
unit SandQue;
// A generic queue, used to store sand grains

interface

type
  PQueueElem = ^TQueueElem;  // Generic element holding user item
  TQueueElem = record
    Item: Pointer;           // The stored user-defined item
    Next: PQueueElem;        // Next element
  end;

  TQueue = class
  public
    Size: Longint;   // We want to be able to store a LOT of grains
    constructor Create;
    destructor Destroy; override;
    procedure Enqueue(Itm: Pointer);
    function Dequeue(var Itm: Pointer): Boolean;
    function Peek(Idx: Word; var Itm: Pointer): Boolean;
  private
    Top, Bottom, Current: PQueueElem;
    Position: Word;
  end;

implementation

{----------------------- TQueue -----------------------}

constructor TQueue.Create;
begin
  inherited Create;
  Size := 0;                 // Queue is empty
  Position := 0;
  Top := nil;
  Bottom := nil;
  Current := nil;
end;


destructor TQueue.Destroy;
var
  Itm: Pointer;
begin
  { Remove any remaining elements before destroying the queue.
    Note that user items are NOT disposed as TQueue doesn't know their
    types. Therefore user should always empty the queue himself and
    dispose the items before destroying the queue. }
  while Size > 0 do
    Dequeue(Itm);
  inherited Destroy;
end;


procedure TQueue.Enqueue(Itm: Pointer);
var
  P: PQueueElem;             // We need a record for the user item
begin
  New(P);
  P^.Item := Itm;
  P^.Next := nil;
  if Size = 0 then
  begin
    Top := P;
    Bottom := P;
    Current := P;
  end;
  Bottom^.Next := P;
  Bottom := P;
  Inc(Position);
  Inc(Size);
end;


function TQueue.Dequeue(var Itm: Pointer): Boolean;
var
  P: PQueueElem;
begin
  Dequeue := False;
  if Size > 0 then           // Same as: if Top <> NIL
  begin
    Itm := Top^.Item;
    P := Top;
    Top := Top^.Next;
    if Current = Itm then
    begin
      Current := Top;
      if Top = nil then
        Position := 0
      else
        Position := 1;
    end
    else
      Dec(Position);
    Dispose(P);
    Dec(Size);
    Dequeue := True;
  end;
end;


function TQueue.Peek(Idx: Word; var Itm: Pointer): Boolean;
var
  P: PQueueElem;
  I: Word;
begin
  Itm := nil;
  Peek := False;

  if Idx <= Size then        // Does the element exist?
  begin
    if Position <= Idx then
    begin
      P := Current;          // Traverse from current position
      for I := 1 to Idx-Position do
        P := P^.Next;
    end
    else
    begin
      P := Top;              // Traverse from start
      for I := 1 to Idx-1 do
        P := P^.Next;
    end;

    Itm := P^.Item;
    Current := P;
    Position := Idx;
    Peek := True;
  end;
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?