这一问题已经得到圆满解决,只需对表扫描两次
应该不会再有更高效率!!!!!!!!
调试成功!!!!!
1. 父子关系表生成树
// 此程序专门用于父子关系表生成树。
// 在查找父节点时使用了两分法。
// 在 5000个节点的情况下最多找 13 14次,
// 而且这一查找是在内存中进行的,大大提高了效率
// 表字段说明
// id 项目标识
// pId 相应父项目标识
// ItemName 项目名称
// 表中项目顺序要求,父项目在子项目前
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, DBTables, Db, ComCtrls, Grids, DBGrids, ADODB,
commctrl; //需要使用这个单元
type
TForm1 = class(TForm)
TreeView1: TTreeView;
Button1: TButton;
ADOTable1: TADOTable;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
type MyItem=Record
id:string;
p:HTreeItem; //树节点句柄,也是节点的唯一标识。而且节省空间
end;
var Its:array of MyItem;
function getIdIndex(var Its:array of MyItem;nStart,nEnd:integer;id:string):Integer;
////// 两分法搜索节点,这是效率的基础
var
n:integer;
begin
Result:=-1;
if nEnd<nStart then exit;
if (nEnd=nStart) then begin
if its[nEnd].id =id then Result:=nEnd;
Exit;
end;
if (id<its[nStart].id) or (id>its[nEnd].id) then exit;
n:=((nStart+nEnd) shr 1);
if id > its[n].id then Result:=getIdIndex(its,n+1,nEnd,id)
else Result:=getIdIndex(its,nStart,n,id);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
n,nItems:integer;
s,st,sName:String;
Node:TTreeNode;
begin
with AdoTable1 do
begin
//取出所有非叶节点Id,因为这些节点可能会重复使用
//这些节点都在父节点 pid 中。
active:=false;
indexName:='AAA';
indexFieldNames:='pId';
active:=true;
First;
s:='';
n:=0;
while not(eof) do begin
st:=trim(FieldbyName('pId').asstring);
if (st<>'*') and (st<>s) then begin
inc
;
setLength(Its,n);
Its[n-1].id:=st;
Its[n-1].p:=nil;
s:=st;
end;
next;
end;
nItems:=n;
//这时生成树,只要按表中原记录顺序扫描一遍就行
active:=false;
indexName:='';
indexFieldNames:='';
active:=true;
first;
while not(eof) do begin
s:=trim(FieldbyName('Id').asstring);
st:=trim(FieldbyName('pId').asstring);
sName:=trim(FieldbyName('ItemName').asstring);
if (st='*') then begin //处理根节点,肯定还没有添加
node:=Treeview1.Items.AddChild(nil,sName);
n:=getIdIndex(Its,0,nItems-1,s); //应该都能找到
Its[n].p:=node.itemid;
end else begin
n:=getIdIndex(Its,0,nItems-1,st); //找到根节点
node:=Treeview1.Items.GetNode(Its[n].p);
node:=Treeview1.Items.AddChild(node,sName);
n:=getIdIndex(Its,0,nItems-1,s); //找到节点
if n>=0 then its[n].p:=node.ItemId ;
//没找到的是叶节点,不需要处理
end;
next;
end;
end;
setLength(its,0);
end;
end.