首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 2009 泛型堆疊 TStack<T> 完整教學:LIFO 資料結構實戰

     編輯:Delphi

堆疊 (Stack) 基本觀念

堆疊 是「後進先出」 (LIFO, Last In First Out) 的資料結構。想像一疊盤子:最後放上去的盤子,最先被拿走。Delphi 2009 的 TStack<T> 提供泛型強型別支援,適用於:

  • 函式呼叫堆疊追蹤
  • Undo/Redo 機制
  • 運算式求值 (中綴轉後綴)
  • 遞迴演算法的非遞迴轉換

執行效果動畫

核心 API 速查

方法/屬性說明備註
Push(item)壓入元素 (推入堆疊頂端)無回傳值
Pop彈出並移除堆疊頂端元素回傳 T,空堆疊會拋出例外
Peek查看堆疊頂端元素不移除回傳 T,空堆疊會拋出例外
Count目前元素總數唯讀屬性
Clear清空堆疊不釋放元素物件 (除非用 TObjectStack)
ToArray轉為陣列 (頂端在前)回傳 TArray<T>

完整實作範例:記錄資料堆疊

資料結構定義


type
  TRec = record
    Name: string;
    Age: Word;
  end;

var
  Stack: TStack<TRec>;

表單操作邏輯


procedure TForm1.FormCreate(Sender: TObject);
begin
  Stack := TStack<TRec>.Create;
  Memo1.Clear;
  Button1.Caption := '壓棧';
  Button2.Caption := '出棧';
  Button3.Caption := '查看下一個出棧';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Stack.Free;
end;

// 壓棧
procedure TForm1.Button1Click(Sender: TObject);
var
  rec: TRec;
begin
  rec.Name := StringOfChar(Char(65 + Random(26)), 3); // 隨機 3 大寫字母
  rec.Age := Random(150);
  Stack.Push(rec);
  Caption := Format('目前堆疊筆數: %d', [Stack.Count]);
  Memo1.Lines.Add(Format('%s, %d', [rec.Name, rec.Age])); // 同步顯示
end;

// 出棧
procedure TForm1.Button2Click(Sender: TObject);
var
  rec: TRec;
begin
  if Stack.Count = 0 then Exit;
  rec := Stack.Pop;
  ShowMessage(Format('彈出: %s, %d', [rec.Name, rec.Age]));
  Caption := Format('目前堆疊筆數: %d', [Stack.Count]);
  Memo1.Lines.Delete(Memo1.Lines.Count - 1); // 移除最後一行 (對應堆疊頂端)
end;

// 查看頂端
procedure TForm1.Button3Click(Sender: TObject);
var
  rec: TRec;
begin
  if Stack.Count = 0 then Exit;
  rec := Stack.Peek;
  ShowMessage(Format('頂端元素: %s, %d', [rec.Name, rec.Age]));
end;

進階應用場景

1. 瀏覽器前進/後退歷史


var
  BackStack, ForwardStack: TStack<string>;

procedure NavigateTo(url: string);
begin
  if CurrentUrl <> '' then BackStack.Push(CurrentUrl);
  CurrentUrl := url;
  ForwardStack.Clear; // 新導航清空前進歷史
end;

procedure GoBack;
begin
  if BackStack.Count > 0 then
  begin
    ForwardStack.Push(CurrentUrl);
    CurrentUrl := BackStack.Pop;
  end;
end;

2. 運算式括號匹配檢查


function CheckBrackets(const expr: string): Boolean;
var
  stack: TStack<Char>;
  c: Char;
begin
  stack := TStack<Char>.Create;
  try
    for c in expr do
      case c of
        '(', '[', '{': stack.Push(c);
        ')': if (stack.Count = 0) or (stack.Pop <> '(') then Exit(False);
        ']': if (stack.Count = 0) or (stack.Pop <> '[') then Exit(False);
        '}': if (stack.Count = 0) or (stack.Pop <> '{') then Exit(False);
      end;
    Result := stack.Count = 0;
  finally
    stack.Free;
  end;
end;

3. 非遞迴深度優先搜尋 (DFS)


procedure DFS_NonRecursive(start: TTreeNode);
var
  stack: TStack<TTreeNode>;
  node: TTreeNode;
begin
  stack := TStack<TTreeNode>.Create;
  try
    stack.Push(start);
    while stack.Count > 0 do
    begin
      node := stack.Pop;
      ProcessNode(node);
      // 依序壓入子節點 (注意順序影響遍歷順序)
      for var i := node.Count - 1 downto 0 do
        stack.Push(node.Item[i]);
    end;
  finally
    stack.Free;
  end;
end;

效能與記憶體注意事項

  • 動態擴容:內部陣列自動成長,大量資料可用 TStack<T>.Create(Capacity) 預分配
  • 記錄 vs 物件:TStack<TRec> 存放值型別 (記錄),複製語意;TStack<TObj> 存放參考,需自行管理物件生命週期
  • 執行緒安全:非執行緒安全,多執行緒需同步機制
  • 避免 Pop 空堆疊:呼叫前務必檢查 Count > 0

總結

TStack<T> 以泛型封裝經典 LIFO 結構,API 簡潔直觀,配合 Delphi 記錄型別支援,能高效解決回溯、歷史管理、語法分析等經典演算法問題,是演算法實作工具箱中的核心元件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved