我该如何为TTreeNodes实现GetLastNode?

时间:2011-06-06 20:00:05

标签: delphi

当我需要找到TTreeView中的第一个节点时,我会调用TTreeNodes.GetFirstNode。但是,我有时需要在树中找到最后一个节点,并且没有相应的TTreeNodes.GetLastNode函数。

我不想使用Items[Count-1]因为这会导致整个树都与Result := Result.GetNext一起走。当然,这仅在树视图具有大量节点时才有意义。我完全理解虚拟容器控件的优点,但我还没有切换到Virtual TreeView。

到目前为止,我已经提出以下建议:

function TTreeNodes.GetLastNode: TTreeNode;
var
  Node: TTreeNode;
begin
  Result := GetFirstNode;
  if not Assigned(Result) then begin
    exit;
  end;
  while True do begin
    Node := Result.GetNextSibling;
    if not Assigned(Node) then begin
      Node := Result.GetFirstChild;
      if not Assigned(Node) then begin
        exit;
      end;
    end;
    Result := Node;
  end;
end;

任何人都可以:

  1. 在我的逻辑中找到一个缺陷?
  2. 建议改进?
  3. 修改1

    我不愿意保留自己的节点缓存。我一直这样做直到最近,但发现一些难以跟踪非常间歇性的AV,我认为这必定是由于我的缓存不同步。显然,一个解决方案是让我的缓存同步代码正常工作,但我厌恶缓存,因为很难跟踪错误时出现的错误。

3 个答案:

答案 0 :(得分:6)

虽然我不是非退出纯粹主义者,但我认为如果在没有退出的情况下可行,同时保持可读性不变,则可能更喜欢该选项。

所以这里的代码完全相同,因为我认为你不能以任何其他方式(更快)到达终端节点,但没有退出并且稍微紧凑:

function TTreeNodes.GetLastNode: TTreeNode;
var
  Node: TTreeNode;
begin
  Node := GetFirstNode;
  Result := Node;
  if Result <> nil then
    repeat
      Result := Node;
      if Node <> nil then
        Node := Result.GetNextSibling;
      if Node = nil then
        Node := Result.GetFirstChild;
    until Node = nil;
end;

答案 1 :(得分:2)

我之前使用的方法是使用OnAddition事件上的List.Add和OnDeletion事件上的List.Remove维护TList(OnRemove?)。您可以立即访问List.Count-1(或任何您需要的东西)。

发布编辑 - 我不得不说虽然这很好用但我还是长大了并转移到虚拟树视图: - )

答案 2 :(得分:2)

如果我要实施它,这可能是我的初稿。

function TTreeNodes.GetLastNode: TTreeNode;
var
  Node: TTreeNode;
  function GetLastSibling(aNode : TTreeNode) : TTreeNode;
  begin
    if not Assigned(aNode) then
      EXIT(nil);
    repeat
      Result := aNode;
      aNode := Result.GetNextSibling;
    until not Assigned(aNode) ;
  end;
begin
  Node := GetFirstNode;
  if not Assigned(Node) then begin
    exit;
  end;

  repeat
    Result := GetLastSibling(Node);
    Node := Result.GetFirstChild;
  until not Assigned(Node);
end;

我发现这稍微更具可读性。但它可能稍慢一点。

我不确定这种方法是否比项[Count-1]更快,在某些情况下,它可能更慢,因为TTreeNodes实际缓存通过items属性访问的最后一个节点。