求树形结构的实现方法。(100分)

  • 主题发起人 主题发起人 xuming
  • 开始时间 开始时间
X

xuming

Unregistered / Unconfirmed
GUEST, unregistred user!
数据库结构如下:
item belong scale id
三水 佛山 3 00001000060000100002
南海 佛山 3 00001000060000100001
日本 根 0 00004
英国 根 0 00003
美国 根 0 00002
中国 根 0 00001
深圳 广东 2 000010000600002
佛山 广东 2 000010000600001
广东 中国 1 0000100006
重庆 中国 1 0000100004
天津 中国 1 0000100003
上海 中国 1 0000100002
北京 中国 1 0000100001
如何才能输出以下的界面:
中国
北京
广东
佛山
南海
三水
深圳
上海
天津
重庆
英国
日本
美国
 
等等,我马上给你找
 
谢谢希望能找到吧。我的邮箱是:dgxum@163.net
 
这是我在网上找到的最快的算法
function TafDir.BuildTree(DataSet: TADODataSet; TV: TTreeView; SelfField,
SelfName, ParentField: String; ClassID: Integer): boolean;
{ 以下子函数为在表中查找第一个PNode=AIndex的记录}
function FindKey(AIndex: integer; FFirst:boolean): boolean;
begin
Result:=DataSet.Locate(ParentField,AIndex,[loCaseInsensitive]);
end;
{ 以下函数在FindKey的基础上找出下一个符合的记录}
function FindNext(AIndex: integer): boolean;
begin
DataSet.Next;
if DataSet.Eof then
Result:=false
else
Result:=DataSet.FieldValues[ParentField]=AIndex;
if not Result then DataSet.Prior;
end;
{ 以下函数据构造当前结点的一级子树 }
function GetChildNode(index: integer; ANode: TTreeNode):integer;
var
MyNode:PNode;
Node:TTreeNode;
begin
if FindKey(index,true) then
begin
new(MyNode);
with DataSet do
begin
MyNode^.ID :=FieldValues[SelfField];
MyNode^.bHasDoc := NOT FieldByName('FileName').IsNull;
MyNode^.FBM :=GetBookmark;
end;
Node:=TV.Items.AddChild(ANode,DataSet.FieldValues[SelfName]);
Node.Data:=MyNode;
//显示进度条
prg.Progress := prg.Progress + 1;

Result:=1;
while FindNext(index) do
begin
new(MyNode);
with DataSet do
begin
MyNode^.pID := FieldValues[ParentField];
MyNode^.ID :=FieldValues[SelfField];
MyNode^.bHasDoc := NOT FieldByName('FileName').IsNull;
MyNode^.FBM :=GetBookmark;
end;
Node:=TV.Items.AddChild(ANode,DataSet.FieldValues[SelfName]);
Node.Data:=MyNode;
//显示进度条
prg.Progress := prg.Progress + 1;
Result:=Result+1;
end;
end
else
Result:=0;
end;
{ 以下函数据以ANode 为结当,构造一棵属于自己的子树}
procedure BuildMe(AIndex: integer; ANode: TTreeNode);
var
NodeNum:integer;
Node:TTreeNode;
i:integer;
begin
NodeNum:=GetChildNode(AIndex,ANode);
if NodeNum>0 then
begin
if ANode=nil then Node:=TV.Items.GetFirstNode
else
Node:=ANode.getFirstChild;
for i:=1 to NodeNum do
begin
BuildMe(PNode(Node.Data)^.ID,Node);
Node:=ANode.GetNextChild(Node);
end;
end;
end;
// 组合部份
var
time:TDateTime;
oldcur:TCursor;
begin
time := Now;

oldcur:=Screen.Cursor;
Screen.Cursor :=crHourGlass;
tvwClass.Enabled := False;
TV.Items.BeginUpdate;

prg := TGauge.Create(nil);
Try
prg.Parent:=sb;
prg.SetBounds(sb.Panels[0].Width+3,3,Self.Width-sb.Panels[0].Width-8,sb.Height-4);
prg.BackColor:=clBtnFace;
prg.ForeColor:=clInactiveCaption;
prg.BorderStyle:=bsNone;

with DataSet do
Begin
Close;
Parameters.ParamByName('ClassID').Value := ClassID;
Open;
prg.Visible := True;
prg.MaxValue := RecordCount;
prg.Progress := 1;
end;

sb.Panels[0].Text := '正在清除目录结构...';
sb.Refresh;
FreeTvwData(TV);
TV.Items.Clear;
sb.Panels[0].Text := '正在载入目录结构...';
sb.Refresh;
BuildMe(0,nil);
Result:=true;
Finally
Screen.Cursor := oldCur;
TV.Items.EndUpdate;
tvwClass.Enabled := True;
prg.Free;
end;
sb.Panels[0].Text := '载入目录耗时:'+FormatDateTime('nn:ss:zz',now-time);
end;
 
关注,希望不用递归,小弟近来把CSDN和DFW快查了N遍,但最终也没有找到比较好的算法!

希望高手可以给出代码~

可以帮助加分!!(一定有信誉!!)
 
BDFan:
你给出的函数所用的数据库是怎样的一个结构呀?
 
按scale 索引,数据量不大一次扫描。
数据量大,两次扫描。
 
jsxjd:我的水平太差了,你能告诉我如具体的实现方法吗?谢谢!
 
oracle中有树形遍历的Sql语句。可以实现按要求的顺序显示,再生成树
 
给你提示:先对数据排序,然后就好做多了。。
 
找了一个控件,Develop Express系列的,搞定
 
用bom 结构呀。
 
人在昆明:
我就是想做BOM呀,有没有例子呀?
 
bom 结构是很复杂的,如果自己来写就要写好多的树形上的控制,要用到指针。
不过我投机取巧,用了一个组件,呵呵!
 
借用刘艺书中的一段,在我以前学树结构时给过帮助
如下:
 
各位,找了一个控件,Developer Express 的DBTreeView,但现在还不太清楚使用方法。
谁有?HELP。。。。。。。
 
sorry,刚去吃饭了。代码如下,希望对你有帮助。
procedure TForm1.LoadTree;
var
str: string;
curID, nodeTxt, iTxt: string;
level, i : integer;
mynode: array[0..6] of TTreenode; //假设最多有六层
begin
tree.Enabled:=True;
tree.Items.Clear;
level:=0;
mynode[level]:=tree.Items.Add(Tree.Topitem,cTreeRootTxt);
mynode[level].ImageIndex:=11;

iTxt:='';
for i:=1 to StrToInt(cTreeCodeFormat[cTreeMaxLevel]) do
begin
iTxt:=iTxt+'0';
end;
str:='SELECT * FROM T### WHERE right(DM,'+cTreeCodeFormat[cTreeMaxLevel]+')='+''''+iTxt+'''';
str:= str+' order by dm';
with treeDB do
begin
close;
SQL.clear;
SQL.Add(str);
try
open;
first;
while not eof do
begin
curID:=trim(FieldByName('id').asstring);
nodeTxt:=curID+'-'+trim(FieldByName('item').asstring);
level:=FieldByName('scale').asinteger;
if (level>0)and(level<cTreeMaxLevel) then
begin
mynode[level]:=tree.Items.AddChild(mynode[level-1],nodeTxt);

//图标授予
case level of
1: //根结点
begin
case WORD(curID[1]) of
72: mynode[level].ImageIndex := 0;
73: mynode[level].imageindex := 1;
74: mynode[level].imageindex := 2;
77: mynode[level].imageindex := 3;
81: mynode[level].imageindex := 4;
83: mynode[level].imageindex := 5;
90: mynode[level].imageindex := 6;
end;
mynode[level].SelectedIndex := 7;
end;
2: begin mynode[level].imageindex := 8; mynode[level].selectedindex := - 1 end;
3: begin mynode[level].imageindex := 9; mynode[level].selectedindex := - 1 end;
4: begin mynode[level].imageindex := 10; mynode[level].selectedindex := - 1 end;
5: begin mynode[level].imageindex := 11; mynode[level].selectedindex := 12 end;
end;
//mynode[level].ImageIndex:=2;
end;
next; //下一条记录
end;
finally
close;
end;
mynode[0].Expand(False); //展开树
screen.Cursor:=crDefault;
end;
end;
 
第一次先读入根节点。
等待双击事件后,再读下一层。如此。。。。双击,读下一层。
这样是不是就能省很多事呢?
呵呵
 
用dbtreeview
 
后退
顶部