天天看点

数据库表TUniTreeView树的快速生成

根据数据表的内容生成TUniTreeView树状结构,通常的做法就是从顶级开始,然后逐项递归查询遍历生成。这种方法在实现上容易做到,也很容易想到,但是效率比较低,因为数据库的检索(SQL语句需要解释执行,而且是对数据库文件进行操作)还是比较耗时的,尤其是树的层次较多,节点较多的情况。这里介绍的方法是以空间换取时间,只进行一次数据库检索,提取出全部数据,然后一次生成TUniTreeView树状结构。通过SQL语句,让返回的记录按照父节点ID、节点ID进行排序,这样保证每次当前要添加的节点记录的父节点都已经添加到了TUniTreeView树中,剩下的工作就是如何在TreeView树中找到父节点。采用了一个排序的TStringList列表,通过排序列表采用二分查找的快速性能,就能够很快地查找到当前要添加节点的父节点,从而插入到TUniTreeView树的正确位置。 

源代码如下(假定数据表名称为FTree,字段有ID, ParentID, Name):

procedure MakeTree(Query: TUniQuery; TreeView: TUniTreeView);

var

  List: TStringList;

  Node: TuniTreeNode;

  Index: Integer;

begin

  TreeView.Items.BeginUpdate;

  try

    TreeView.Items.Clear;

    List := TStringList.Create;

    try

      List.Sorted := True;

      while not Query.Eof do

      begin

        if Query.FieldByName('ParentID').AsInteger = 0 then { ParentID=0,顶层节点 }

          Node := TreeView.Items.AddChild(nil, Query.FieldByName('Name').AsString)

        else

        begin

          Index := List.IndexOf(Query.FieldByName('ParentID').AsString);

          Node := TreeView.Items.AddChild(TuniTreeNode(List.Objects[Index]), Query.FieldByName('Name').AsString);

        end;

        List.AddObject(Query.FieldByName('ID').AsString, Node);

        Query.Next;

      end;

    finally

      List.Free;

    end;

  finally

    TreeView.Items.EndUpdate;

  end;

end;

procedure TMainForm.UniButton1Click(Sender: TObject);

var

  T: DWORD;

begin

  T := GetTickCount;

  UniQuery1.SQL.Text := 'SELECT * FROM FTree ORDER BY ParentID, ID';

  UniQuery1.Open;

  MakeTree(UniQuery1, UniTreeView1);

  UniLabel1.Caption := Format('MakeTree所用时间: %d ms', [GetTickCount - T]);

end;

继续阅读