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

Delphi 高效生成樹形結構:基於編碼規則的最優算法實戰

     編輯:Delphi

TTreeView 是展示多層級關係資料的最佳控制項,但在資料庫開發中面對層次多、結構複雜的資料,如何快速構造樹形目錄並實現導航?傳統遞歸或多層巢狀迴圈效率低、程式碼冗長。本文介紹基於**編碼字典**的高效算法:程式碼精簡、執行極快、支援任意層次、資料變動無需改代碼。

核心原理:編碼設計規範

  • 資料表需包含 bianma(編碼,字串型)與 name(名稱)欄位
  • 編碼格式以數字位數區分層次,同層位數相同,層次遞增
  • 範例格式 '222' 表示三層,每層 2 位:第 1 層 2 碼(10~99)、第 2 層 4 碼(1001~1099)、第 3 層 6 碼
  • 程式透過分析編碼長度判斷節點層級,自動建立父子關係

關鍵常數定義 (PubVar.pas)

const
  cTreeCodeFormat = '222';  // 編碼格式:XX XX XX
  cTreeMaxLevel = 3;        // 最大層次
  cTreeRootTxt = '城市';     // 根節點名稱

核心算法:單次遍歷建樹

procedure TForm1.LoadTree(treeDB: TDBDataSet);
var curID, nodeTxt: string; level: Integer; mynode: array[0..3] of TTreeNode;
begin
  Screen.Cursor := crHourGlass;
  Tree.Items.Clear;
  level := 0;
  // 根節點
  mynode[level] := Tree.Items.Add(nil, cTreeRootTxt);
  mynode[level].ImageIndex := 1;

  with treeDB do try
    if not Active then Open;
    First;
    while not Eof do begin
      curID := Trim(FieldByName('bianma').AsString);
      nodeTxt := curID + '-' + Trim(FieldByName('cityname').AsString);
      level := GetNodeLevel(cTreeCodeFormat, curID); // 解析層級
      if level > 0 then
        mynode[level] := Tree.Items.AddChild(mynode[level-1], nodeTxt); // 掛在上層節點
      mynode[level].ImageIndex := 2;
      Next;
    end;
  finally Close; end;
  mynode[0].Expand(False);
  Screen.Cursor := crDefault;
end;

function TForm1.GetNodeLevel(sFormat, sCode: string): Integer;
var i, iLen: Integer;
begin
  Result := -1; iLen := 0;
  if (sFormat <> '') and (sCode <> '') then
    for i := 1 to Length(sFormat) do begin
      iLen := iLen + StrToInt(sFormat[i]);
      if Length(sCode) = iLen then begin Result := i; Break; end;
    end;
end;

同步更新:增刪改無需重構全樹

透過右鍵選單操作節點,直接對應資料庫操作並同步更新 TreeView:

  • 新增子節點:查詢當前節點最大子編碼 +1,Items.AddChild + Table.Insert
  • 重命名:Node.Text := 新名稱 + Table.Edit/Post
  • 刪除:檢查子節點/根節點保護,Node.Delete + Table.Delete

關鍵輔助函數:

// 取得當前節點編碼
function GetCurrentNodeBianma(curNode: TTreeNode): string;
var p: Integer; begin p := Pos('-', curNode.Text); Result := Copy(curNode.Text, 1, p-1); end;

// 取得子節點最大編碼(含自動補位邏輯)
function GetCurrChildNodeMaxMa(curNode: TTreeNode): string;
// ... 以 SQL LIKE 查詢同前綴最大編碼,無子節點時自動補 '00'

優勢總結

傳統遞歸/巢狀迴圈編碼字典法
多次查詢/遞歸調用單次順序遍歷
層次固定需改代碼修改常數即可適應任意層次
資料變動需重構全樹增刪改局部同步,無閃爍
效能隨資料量指數下降線性複雜度,極快

適用場景擴展

  • 組織架構、產品分類、知識庫目錄、選單權限樹
  • 任意「編碼+名稱」字典表維護介面
  • 點擊節點直接顯示關聯明細(Master-Detail)

原文發表於《電腦編程技巧與維護》2003 年第 1 期 P27。此算法經多年實戰驗譱,至今仍是 Delphi 資料庫樹形介面開發的經典範式。

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