晕死了treeview的第归生成问题(50分)

  • 主题发起人 主题发起人 陈晨
  • 开始时间 开始时间

陈晨

Unregistered / Unconfirmed
GUEST, unregistred user!
数据库结构
rid, id, lid
rid,lid分别为
id的左右儿子
要求建立一个树形结构

id
|--lid
|--rid

procedure addno(pnode:ttreenode;ADO:Tadotable);
var psib,sib:ttreenode;
st:integer;
id:string;
lid,rid:string;
str,str1:string;
begin
psib:=pnode;
//st:=pos('...',psib.Text);
//if st>0 then begin
STR1:=psib.text;
// id:=copy(STR1,st+3,10);
if ado.Locate('id',str1,[]) then
begin

showmessage(inttostr(adotable1.recno));
begin
if ado.fieldvalues['rid']<>null then begin
str:=ado.FieldValues['rid'];//ado.FieldValues['name']+'...'+
adotable1.Locate('id',str1,[]);
sib:=treeview1.Items.AddChild(psib,str);
addno(sib,adotable1);
end;
if ado.fieldvalues['lid']<>null then begin
str:=ado.FieldValues['lid']; // ado.FieldValues['name']+'...'+
adotable1.Locate('id',str1,[]);
sib:=treeview1.Items.AddChild(psib,str);
addno(sib,adotable1);
end;
end;

end;

end;

在线等待
 
没有太看懂,将你的表结构描述一下好吗?
 
例如
003,001,002
004,002,005
006,003,009
007,005,008

每一行的中心为父节点,左右分别为叶子节点建立
treeview的结构
001
002
004
005
007
008
003
006
009

 
嘿嘿,很怪的需求,个人觉得应该是数据库设计的不合理,导致程序实现比较麻烦,但是单纯这个确实是一个算法的好问题,偶想想看。。。
 
可以考虑不用AdoTable,改用AdoQuery,使用多个SQL语句吧,因为Locate速度比较慢,所以不推荐使用。
但是AdoQuery也有问题,因为是多个SQL语句,速度差不多。但是条理稍微清晰一些。
 
还要连接其他的表得到对应id得到名字,还是用table的lookup字段。
 
随便写了一点代码,基本能够实现你的功能,如果你要求不用多个SQL,将sql改一下就应该可以了。
不过还是那句话,如果真的要实现这个需求,你的表结构应该设计是不合理的。

procedure TForm1.Button1Click(Sender: TObject);
begin
Add_Nodes(nil, '100');
end;

procedure TForm1.Add_Nodes(ANode: TTreeNode; Aid: String);
var
lNode: TTreeNode;
lTmpList: TStringList;
i: Integer;
begin
lTmpList := TStringList.Create;

with TreeView1.Items do
begin
lNode := AddChild(ANode, Aid);
AdoQuery1.Close;
AdoQuery1.SQL.Text := 'Select rid from Table3 Where id=' + QuotedStr(Aid) +
' Union ' +
' Select lid from Table3 Where id=' + QuotedStr(Aid);
AdoQuery1.Open;

While not AdoQuery1.Eof do
begin
lTmpList.Add(AdoQuery1.Fields[0].AsString);
AdoQuery1.Next;
end;

for i := 0 to lTmpList.Count - 1 do
Add_Nodes(lNode, lTmpList);
end;

lTmpList.Free;
end;
 
上面的代码效率很底的说

方法一:
而且根据你的结构,你不可能一次取出所有数据,既然不能一次取出所有数据,那么建议你在用户事件中装配相应的子树

方法二:
如果你用oracle的话,可以按深度优先的算法一次取出所有数据(一条select,任意结点开始),
再用10行多的代码完成树的装载,这是最简洁的方法。效率最高(没有递归,没有locate等)
建议你按深度优先的算法做一个存储过程,返回(记得计算 level ) ,然后根据level装载到树
这一点你可以找一篇关于ms sql 构造自定义函数的文章,其中提到这个例子

good luck
 
你的例子和树节点顺序比较混乱,倒底是先加右节点,还是左节点。
先加左节点应为:
001
003
006
009
002
004
005
007
008

从文本文件 d:/temp.txt 生成树的程序,从表中读出稍加修改即可:
procedure TForm1.Button4Click(Sender: TObject);
var
s1,s2:TStrings;
i,j,ndx:integer;
Node,LNode,RNode:string;
x:TTreeNode;
begin
s1:=TStringList.Create ;
s2:=TStringList.Create ;
s1.LoadFromFile('d:/temp.txt');
for i:=0 to s1.Count-1 do
begin
s2.CommaText:=s1;
Node:=s2[1];
LNode:=s2[0];
RNode:=s2[2];
ndx:=-1 ;
for j:=0 to Treeview1.Items.Count-1 do
if Treeview1.Items[j].Text=node then
begin
ndx:=j;
break;
end;
if ndx>=0 then
x:=treeview1.Items[ndx]
else
x:=treeview1.Items.Add(treeview1.topitem,node);
treeview1.Items.AddChild(x,Lnode);
treeview1.Items.AddChild(x,Rnode);
end;
s1.free;
s2.free;
end;


// D:/temp.txt 如下:
003,001,002
004,002,005
006,003,009
007,005,008
 
表里面没有固定的顺序,所以最后一行才故意打乱的,
 
解决了吗?
 
我用了一个字符串存它们之间的关系
1r
1l
1r2l
1r2r
1l2l
1l2r
...
1r2l3r4r5l
 
给你的代码不是已经实现了!!!!!!!!
上面又是什么意思???
 
实现了谢谢各位
 
后退
顶部