如何用递归算法构建 treeview ?(数据库没使用 parent ID) ( 积分: 100 )

  • 主题发起人 主题发起人 kmask
  • 开始时间 开始时间
K

kmask

Unregistered / Unconfirmed
GUEST, unregistred user!
不知该怎样写,网上看到的例子都是数据库使用&nbsp;parentID&nbsp;的,不适用,因为此数据库的数据可能有多个&nbsp;parentID,到底该怎样处理啊?&nbsp;彻底晕了<br><br>数据库结构如下<br><br>组号&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;成员编号&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;备注<br>01001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;005&nbsp;<br>01001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0069<br>005&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0069<br>0069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00037<br>...<br><br>也就是说,数据库中的每一个组,都有可能包含成员,而且级数不限<br><br><br>江湖救急,大家支招,或者说怎样更改数据库结构也可以,多谢啦
 
我也有同样的问题,期待中...
 
不需要递归,一次只读取一层数据,下一层用临时结点代替,展开时才真正读取数据,<br>这样可以大大加快速度,因为一次只读一层数据,而不是读取整个树的数据.<br><br>代码如下:<br><br>//创建根结点<br>procedure&nbsp;TForm1.FormCreate(Sender:&nbsp;TObject);<br>var<br>&nbsp;&nbsp;Node:&nbsp;TTreeNode;<br>&nbsp;&nbsp;Text:&nbsp;string;<br>begin<br>&nbsp;&nbsp;TreeView1.Items.Clear;<br>&nbsp;&nbsp;with&nbsp;ADOQuery1&nbsp;do<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;Close;<br>&nbsp;&nbsp;&nbsp;&nbsp;SQL.Text:=&nbsp;'select&nbsp;distinct&nbsp;组号&nbsp;from&nbsp;表1&nbsp;where&nbsp;组号&nbsp;not&nbsp;in&nbsp;(select&nbsp;成员编号&nbsp;from&nbsp;表1)';<br>&nbsp;&nbsp;&nbsp;&nbsp;Open;<br>&nbsp;&nbsp;&nbsp;&nbsp;First;<br>&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;not&nbsp;Eof&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Text:=&nbsp;FieldByName('组号').AsString;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Node:=&nbsp;TreeView1.Items.Add(nil,&nbsp;Text);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeView1.Items.AddChild(Node,&nbsp;'');&nbsp;//此为临时结点,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next;<br>&nbsp;&nbsp;&nbsp;&nbsp;end;<br>&nbsp;&nbsp;end;<br>end;<br><br>//展开时删除临时结点,并创建真正的结点<br>procedure&nbsp;TForm1.TreeView1Expanding(Sender:&nbsp;TObject;&nbsp;Node:&nbsp;TTreeNode;<br>&nbsp;&nbsp;var&nbsp;AllowExpansion:&nbsp;Boolean);<br>var<br>&nbsp;&nbsp;ChildNode:&nbsp;TTreeNode;<br>&nbsp;&nbsp;Text:&nbsp;string;<br>begin<br>&nbsp;&nbsp;if&nbsp;(Node.Count=1)&nbsp;and&nbsp;(Node.getFirstChild.Text='')&nbsp;then<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;Node.DeleteChildren;&nbsp;//删除临时结点<br>&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;ADOQuery1&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Close;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SQL.Text:=&nbsp;'select&nbsp;distinct&nbsp;成员编号&nbsp;from&nbsp;表1&nbsp;where&nbsp;组号='''&nbsp;+&nbsp;Node.Text&nbsp;+&nbsp;'''';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Open;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;First;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;not&nbsp;Eof&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Text:=&nbsp;FieldByName('成员编号').AsString;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChildNode:=&nbsp;TreeView1.Items.AddChild(Node,&nbsp;Text);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeView1.Items.AddChild(ChildNode,'');&nbsp;//此为临时结点,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Next;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>&nbsp;&nbsp;&nbsp;&nbsp;end;<br>&nbsp;&nbsp;end;<br>end;
 
谢谢楼上兄弟的资料,但,有些不合适,因为程序有时候要在后台处理数据,并非单一的treeview&nbsp;应用。仍然感谢
 
递归方法可由djrj的程序改造而来:<br>首先查找到所有的顶层节点,此处可参照djrj的程序“//创建根结点”部分,对每个根节点插入到TreeView时调用Add方法返回的TreeNode调用插入子节点InsertChildren方法,插入子节点InsertChildren伪代码如下:<br><br>procedure&nbsp;InsertChildren(CurrentNode:&nbsp;TTreeNode);<br>var<br>&nbsp;&nbsp;ChildNode:&nbsp;TTreeNode;<br>begin<br>&nbsp;&nbsp;for&nbsp;CurrentNode的每一个子节点&nbsp;do&nbsp;&nbsp;//查找子节点方法可以参见djrj程序后半部分<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;ChildNode:=&nbsp;CurrentNode.AddChild(第i个子节点的数据)&nbsp;//i为循环变量;<br>&nbsp;&nbsp;&nbsp;&nbsp;InsertChildren(ChildNode);<br>&nbsp;&nbsp;end;<br>end<br>这个递归不需要特别指出递归出口,因为CurrentNode的每一个子节点总是有限可数个,且叶子节点的子节点总是0个。<br><br>根据楼主给出的示例表来看,可能数据中层之间会有交叉,比如第二、三行的成员编号均为0069,也就是说组01001和组005都包含成员0069,而组005同时又是组01001的成员,这样实际上形成了图而且不是一个分级图的状况,这个和树的结构有较大的不同,使用Treeview来表现似乎不妥,不知道是否为楼主笔误。上述程序在这种情况下仍可运行,如对于示例表就会在组01001和组005的节点下分别挂上一个相同的以成员0069为根的树。
 
如果编码采用会计科目式的,请参考下文:<br>&lt;&lt;用树型结构表示科目代码的一种高效算法&gt;&gt;<br>到goolge里找一下。
 
我做的类似的代码,给一楼参考一下:<br><br>procedure&nbsp;TMainFrm.DisPlay(DisNode:&nbsp;TTreeNode);<br>var<br>&nbsp;&nbsp;tmpNode:&nbsp;TTReeNode;<br>&nbsp;&nbsp;I:&nbsp;integer;<br>begin<br>&nbsp;&nbsp;&nbsp;&nbsp;//显示目录<br>&nbsp;&nbsp;qry1.Active&nbsp;:=&nbsp;False;<br>&nbsp;&nbsp;qry1.SQL.clear;<br>&nbsp;&nbsp;qry1.SQL.add('select&nbsp;*&nbsp;from&nbsp;RouteLayer&nbsp;where&nbsp;Up_Route='''&nbsp;+&nbsp;IntToStr(Integer(DisNode.Data))&nbsp;+&nbsp;'''');<br>&nbsp;&nbsp;qry1.Active&nbsp;:=&nbsp;True;<br>&nbsp;&nbsp;while&nbsp;not&nbsp;qry1.Eof&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmpNode&nbsp;:=&nbsp;Tv1.Items.AddChild(DisNode,&nbsp;qry1.fieldByName('Route_Name').AsString);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmpNode.Data&nbsp;:=&nbsp;Pointer(qry1.fieldByName('Route_ID').AsInteger);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmpNode.ImageIndex&nbsp;:=&nbsp;GetIconIndex(PChar(gDataBasePath&nbsp;+&nbsp;'PicManage'));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmpNode.SelectedIndex&nbsp;:=&nbsp;GetIconIndex(PChar(gDataBasePath&nbsp;+&nbsp;'PicManage'));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;qry1.Next;<br>&nbsp;&nbsp;&nbsp;&nbsp;end;<br>&nbsp;&nbsp;for&nbsp;I&nbsp;:=&nbsp;0&nbsp;to&nbsp;DisNode.Count&nbsp;-&nbsp;1&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DisPlay(DisNode.Item);<br>&nbsp;&nbsp;&nbsp;&nbsp;end<br>end;
 

Similar threads

后退
顶部