質問は本質的に、再帰なしでツリーをトラバースする方法を尋ねます。ツリーをたどる方法はたくさんあります。ツリーがたまたまビジュアル コントロールのノードで表されているという事実は関係ありません。
一部のアルゴリズムでは、走査を再帰的に考える方が簡単です。このようにして、現在アクティブなノードをスタック上の引数として保持することにより、プログラミング言語がツリー内のどこにいるかを追跡できるようにします。再帰を使用したくない場合は、進行状況を自分で追跡する必要があります。そのための一般的なツールには、スタックとキューが含まれます。
preorder トラバーサルとは、ノードにアクセスしたときに、ノードの子に対してアクションを実行する前に、そのノードのデータに対してアクションを実行することを意味します。これは、ツリー ビュー コントロールの各ノードを上から下に移動することに対応します。スタックを使用して次のように実装できます。
procedure PreorderVisit(Node: TTreeNode; Action: TNodeAction);
var
Worklist: TStack<TTreeNode>;
i: Integer;
begin
Worklist := TStack<TTreeNode>.Create;
try
Worklist.Push(Node);
repeat
Node := Worklist.Pop;
for i := Pred(Node.Items.Count) downto 0 do
Worklist.Push(Node.Items[i]);
Action(Node);
until Worklist.Empty;
finally
Worklist.Free;
end;
end;
子を逆の順序でスタックにプッシュして、希望の順序でポップされるようにします。
そのコードでAction
は、各ノードで実行する必要があるタスクを表します。コードで指定されているように外部関数として使用するかPreorderVisit
、タスク固有のコードを含む特殊なバージョンの を作成することができます。
ただし、TTreeView は実際にはtreeを表していません。まさに森(木の集まり)です。これは、ルートを表す単一のノードがないためです。ただし、上記の関数を使用してツリー内のすべてのノードを簡単に処理できます。
procedure PreorderVisitTree(Tree: TTreeView; Action: TNodeAction);
var
i: Integer;
begin
for i := 0 to Pred(Tree.Items.Count) do
PreorderVisit(Tree.Items[i], Action);
end;
TTreeView の特定の構造を利用して事前注文トラバーサルを行う別の方法はGetNext
、各ノードの組み込みメソッドを使用することです。
procedure PreorderVisitTree(Tree: TTreeView; Action: TNodeAction);
var
Node: TTreeNode;
begin
if Tree.Items.Count = 0 then
exit;
Node := Tree.Items[0];
repeat
Action(Node);
Node := Node.GetNext;
until not Assigned(Node);
end;
Firemonkey ツリー ビューの非表示ノードを取得する方法はないようです。GUI から情報を抽出しようとするのではなく、内部ツリー データ構造を反復処理することで、より良い結果が得られる場合があります。