您现在的位置:首页 >> 基础算法 >> window基础 >> 内容

Delphi中另一种较为高效的TreeList生成算法

时间:2011/9/3 15:32:53 点击:

  核心提示:但是非叶节点的Filter操作依然是无可避免的。而Filter又是影响整个生成的最重要因素,因此当带子节点的节点很多时,速度还是要被拖下去的。  后来我看到了一种觉得不错的思路,就是用调整节点的方法来...
但是非叶节点的Filter操作依然是无可避免的。而Filter又是影响整个生成的最重要因素,因此当带子节点的节点很多时,速度还是要被拖下去的。    后来我看到了一种觉得不错的思路,就是用调整节点的方法来形成树。先一次过把所有数据当根节点加进TreeList中,然后再根据它们之间的ID和PID关系来进行节点调整,这样就可以避免数据集的Filter操作了。而影响算法的主要因素,变成了查找关系时的IndexOf操作,和节点移动的方法MoveTo,不过相对于Filter来说,这个肯定要更高效了。    虽然思路不是我先想出来的,不过具体的调整方法是自己想的。 600) this.width = 600;">   procedure GenerateTreeListEx(AKeyField, AParentField: string; ADataSet: TDataSet; ATree: TTreeView);    function CreateNewNode(ADataSet: TDataSet; ATree: TTreeView): TTreeNode;
 var
  pCodeValue: PString;
 begin
  // 这里写你的TreeNode读写逻辑,添加到根节点下就行
  // 现以用Data属性来保存代码值为例,假设代码名字段叫"CodeName",代码值字段叫"CodeValue"
  result := ATree.Add(nil, ADataSet['CodeName']);
  New(pCodeValue);
  pCodeValue^ := ADataSet['CodeValue'] ;
  result.Data := pCodeValue;
 end;   var
 APidList, AItems, AChildItems: TStringList;
 i, j, k, iIndex: integer;
 sPID: string;
begin
 APidList := TStringList.Create;  APidList.Sorted := true;  //把结果进行排序,这样可以通过搜索算法(Find的二分查找)提高索引效率,重要
 ATree.Items.BeginUpdate;
 try
  // 读取数据集
  for i := 1 to ADataSet.RecordCount do
  begin
   if VarIsNull(ADataSet[AParentField]) then
    sPID := 'NULL'
   else
    sPID := ADataSet[AParentField];
   // 查找该PID是不是已经在PidList里存在
   if not APidList.Find(sPID, iIndex) then
    iIndex := APidList.AddObject(ADataSet[AParentField], TStringList.Create);
   with TStringList(APidList.Objects[iIndex]) do
    AddObject(ADataSet[AKeyField], CreateTreeNode(ADataSet, ATree));    ADataSet.Next;
  end;
  // 调整节点
  for i := 0 to APidList.Count - 1 do
  begin
   AItems := TStringList(APidList.Objects[i]);
   for j := 0 to AItems.Count - 1 do
   begin
    if APidList.Find(AItems[j], iIndex) then
    begin
     AChildItems := TStringList(APidList.Objects[iIndex]);
     for k := 0 to AChildItems.Count - 1 do
      TTreeNode(AChildItems.Objects[k]).MoveTo(TTreeNode(AItems.Objects[j]), naAddChild);      // 由于MoveTo会导致节点展开,因此把它重新折叠起来      TTreeNode(AItems.Objects[j]).Collapse(false);
    end;
   end;
  end;
 finally
  // 释放资源等
  for i := 0 to APidList.Count - 1 do APidList.Objects[i].Free;
  APidList.Free;
  ATree.Items.EndUpdate;
 end;
end;  

 比起上次的方法,除了效率外,我觉得这次的方法代码也更为简洁点,没有用到什么栈结构;也不用什么RootFilterText来过滤根节点了。它能得出哪些是根节点(对于一些丢失父节点的节点,也能自动被处理成根节点),这是我觉得比较好的地方。

作者:harryfin 来源:转载
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • 盒子文章(www.2ccc.com) © 2024 版权所有 All Rights Reserved.
  • 沪ICP备05001939号