用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
blazingfire的公告
文章分类
    存档

    原创  高效率从数据库提取数据,创建树形结构图 收藏

    procedure BuildTree(TreeView: TTreeView; DataSet: TDataSet;
      KeyField, ParentField, TitleField: string);
    { 高效建树过程 by blazingfire 2008-05-21 }
    type
      PNodeData = ^TNodeData;
      TNodeData = record
        Key: Integer;
        Parent: Integer;
        Title: string;
        Node: TTreeNode;
      end;

      function CompareKey(Item1, Item2: Pointer): Integer;
      begin
        Result := PNodeData(Item1)^.Key - PNodeData(Item2)^.Key;
      end;

      function BisearchNodeData(Key: Integer; SortedList: TList): PNodeData;
      var
        Lo, Hi, Mid: Integer;
      begin
        Lo := 0;
        Hi := SortedList.Count - 1;
        while Lo <= Hi do
        begin
          Mid := (Lo + Hi) div 2;
          Result := SortedList[Mid];
          if Key > Result^.Key then
            Lo := Mid + 1
          else if Key < Result^.Key then
            Hi := Mid - 1
          else
            Exit {至此已经找到};
        end;
        Result := nil;
      end;

      procedure BuildNode(nData: PNodeData; SortedList: TList);
      var
        ParentData: PNodeData;
      begin
        if nData^.Node = nil then
        begin
          //折半查找父级PNodeData
          ParentData := BisearchNodeData(nData^.Parent, SortedList);
          //父级为空或是本身,就建一个根节点
          if (ParentData = nil) or (ParentData = nData) then
            nData^.Node := TreeView.Items.AddChild(nil, nData^.Title)
          else
          begin
            if ParentData.Node = nil then
              BuildNode(ParentData, SortedList);
            nData^.Node := TreeView.Items.AddChild(ParentData.Node, nData^.Title);
          end;
        end;
      end;

    var
      List, SortedList: TList;
      i: Integer;
      nData: PNodeData;
      fldKey, fldParent, fldTitle: TField;
    begin
      TreeView.Items.BeginUpdate;
      List := TList.Create;
      try
        fldKey := DataSet.FieldByName(KeyField);
        fldParent := DataSet.FieldByName(ParentField);
        fldTitle := DataSet.FieldByName(TitleField);
        TreeView.Items.Clear;

        DataSet.DisableControls;
        try
          //把数据集的数据加载到内存,以备在内存里建树
          DataSet.First;
          while not DataSet.Eof do
          begin
            New(nData);
            nData^.Key := fldKey.AsInteger;
            nData^.Parent := fldParent.AsInteger;
            nData^.Title := fldTitle.AsString;
            nData^.Node := nil;
            List.Add(nData);
            DataSet.Next();
          end;
        finally
          DataSet.EnableControls;
        end;

        SortedList := TList.Create;
        try
          SortedList.Assign(List);
          SortedList.Sort(@CompareKey); //以Key排序,以备用折半查找
          for i := 0 to List.Count - 1 do
            BuildNode(List[i], SortedList);
        finally
          SortedList.Free;
        end;
      finally
        TreeView.Items.EndUpdate;
        for i := 0 to List.Count - 1 do
          Dispose(List[i]);
        List.Free;
      end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ADOQuery1.Close;
      ADOQuery1.SQL.Text := 'SELECT PROCLASSID,PROFCLASSID,PROCLASSNAME from TableName';
      ADOQuery1.Open;
      BuildTree(TreeView1, ADOQuery1, 'PROCLASSID', 'PROFCLASSID', 'PROCLASSNAME');
    end;

    发表于 @ 2008年05月21日 14:21:00 | 评论( loading... ) | 编辑| 举报| 收藏

    旧一篇:如何在Delphi中用代码来完成计算字段的创建 | 新一篇:如何把一个Word文档流直接加载到OleContainer中?

    • 发表评论
    • 评论内容:
    •  
    Copyright © blazingfire
    Powered by CSDN Blog