读书人

加载三层树的有关问题

发布时间: 2012-03-22 17:43:57 作者: rapoo

加载三层树的问题
现在我有一个数据库Test
表结构和数据如入:
ID Name ParentID
1 中国人 00000000
2 浙江人 1
3 湖北人 1
4 杭州人 2
5 绍兴人 2
6 武汉人 3
7 荆门人 3
8 美国人 00000000
9 纽约人 8
10 华盛顿人8
11 曼哈顿人9


现在要根据他们的ID和ParentID的关系加载到树中,呈现层次关系

请问有没有好的算法,不要用到TreeView的SelectChange事件,要求一次性加载。
高手帮忙啊!

[解决办法]
快速创建树的方法 (抛弃拙劣的数据库结构和算法)

1、现在很多人都使用“父-子结构+递归算法”来显示树型的层次结构,但是不得不说这是一种非常拙劣的方式,下面给大家一种简单方便的数据结构和算法,快速显示树型的层次结构:
2、数据库结构
例如表“国家”可以是这样:
编号 名称
----------
01 中国
0101 吉林省
010101 长春市
010102 吉林市
0102 江苏省
010201 南京市
010202 常州市
02 美国
0201 密歇根州
020101 底特律市
0202 华盛顿州
020201 温哥华市
020202 西雅图市
03 澳大利亚
3、在 TreeView 中显示结构
procedure CreateTree;
const
ID_DEPT = 2;
var
nLevel: Integer;
pNodes: array[0..1023] of TTreeNode;
lpID, lpName: string;
begin
ADODataSet1.Close;
ADODataSet1.CommandText := 'SELECT * FROM [国家] ORDER BY [编号] ';
ADODataSet1.Open;
pNodes[0] := nil;
TreeView1.Items.Clear;
with ADODataSet1.Recordset do
while not Eof do
begin
lpID := Fields[ '编号 '].Value;
lpName := Fields[ '名称 '].Value;
nLevel := Length(lpID) div ID_DEPT;
pNodes[nLevel] := TreeView1.Items.AddChild(pNodes[nLevel - 1], lpName);
MoveNext;
end;
end;
4、短短 20 行,一次读取数据。有人可能问为什么把 pNodes 的大小设成 1024?你也可以设成 10000,随你便,不过 TreeView 如果有那么多节点早死机了。


[解决办法]
树的快速创建算法,只需读一次数据库.

unit U_CreateTree;

interface

uses
Classes, ComCtrls, ADODB, SysUtils;

type
PPNodedata=^TNodeData;
TNodeData = record
ID:integer;//节点编号
PID:Integer;//父节点编号
Name:string;//节点名称
child:PPNodedata;//孩子节点
brather:PPNodedata;//兄弟节点
end;
PNodeData = PPNodeData;
TTreeFill1 = class(TThread)
TV: TTreeView;
RootID:Integer;
ptr:PPNodeData;
root:PPNodeData;//根节点
PointNode:PPNodeData;
s:array[0..10000] of PPNodeData;
constructor Create(Root_Id:integer;ATreeView: TTreeView);
private
procedure AddTree(Node: TTreeNode; PN: PNodeData);
protected
procedure Execute; override;
end;

implementation

uses
U_Main, DateUtils;

var count,nodeCount:Integer;
//----------
constructor TTreeFill1.Create(Root_Id:integer;ATreeView:TTreeView);
begin
TV:= ATreeView;
TV.Items.Clear;
RootID:=Root_Id;
inherited Create(False);
end;
//----------
procedure TTreeFill1.Execute;
var Query: TADOQuery;
i,j:Integer;
Node: TTreeNode;
begin
FreeOnTerminate := True;


TV.Items.Clear;
with Query do
begin
Query := TADOQuery.Create(nil);
Connection := frm_Main.ADOC_SQL;//需要更改
Close;
SQL.Clear;
SQL.Add( 'Select * from 部门表 order by 部门编号 ');
Open;
first;
count:=recordcount;
if count> 0 then
begin
for i:=0 to recordcount-1 do
begin
new(PointNode);
PointNode^.child:=nil;
PointNode.brather:=nil;
PointNode^.ID:=fieldbyname( '部门编号 ').AsInteger;
PointNode^.PID:=fieldbyname( '父部门编号 ').AsInteger;
PointNode^.Name:=fieldbyname( '部门名称 ').AsString;
s[i]:= PointNode;
next;
end;
end;
free;
end;
//------创建树----------
for i:=0 to count-1 do
begin
for j:=0 to count-1 do
if s[i]^.PID=s[j]^.ID then
begin
if s[j]^.child=nil then
s[j]^.child:=s[i]
else
begin
ptr:= s[j]^.child;
while (ptr.brather <> nil) do
ptr:=ptr^.brather;
ptr.brather:=s[i];
end;
end;
end;
for i:=0 to count-1 do
if s[i]^.ID=RootID then
begin
root:=s[i]; //根节点
break;
end;
Node:=TV.Items.AddObject(nil,Root^.Name,Root);//创建树的根节点
nodeCount:=0;
Node.ImageIndex := 0;
Node.SelectedIndex := 2;
AddTree(Node,root);
end;

procedure TTreeFill1.AddTree(Node:TTreeNode;PN:PNodeData);
var
nNode: TTreeNode;
PNode,q: PNodeData;
begin
PNode:=PN;
if PNode.child <> nil then
begin
q:=PNode.child;
while (q <> nil) do
begin
nNode:=TV.Items.AddchildObject(Node,q^.Name,q);
nodeCount:=nodeCount+1;
AddTree(nNode,q);
q:=q^.brather;
end;
end;
end;

end.

[解决办法]
1,数据如下:
ModuleCode ModuleName ModuleLevel
---------------------------------------- ---------------------------------------- -----------
11 系统维护 1
21 基础资料 1
31 采购管理 1
31-31 采购收货单 2
31-31-101 采购收货单-开单 3
31-31-102 采购收货单-修改 3
31-31-103 采购收货单-删除 3
31-41 采购付款单 2
31-41-101 采购付款单-开单 3
31-41-102 采购付款单-修改 3
31-41-103 采购付款单-删除 3
31-51 采购退货单 2
31-51-101 采购退货单-开单 3
31-51-102 采购退货单-修改 3
31-51-103 采购退货单-删除 3
32 销售管理 1


{******************************************************************************}
--模块编码
2 SQL 语句如下,注意 ORDER BY ModuleCode
SELECT ModuleCode,ModuleName,ModuleLevel FROM SB_Modules ORDER BY ModuleCode
/*
SELECT ModuleCode,ModuleName,LeafModuleSign,ParentModuleCode,ModuleLevel FROM SB_Modules ORDER BY ModuleCode
*/
{******************************************************************************}

3,代码如下

procedure TfrmPurviewAssign.BuildCheckTree(pDataSet:TDataSet);
var
iLevel:Integer;
sCode,sName:string;
MyNode:array[0..10]of TTreeNode;//保存各级节点,最长支持 10 级(重点)
begin
Screen.Cursor:=crHourGlass;
ckTreePurview.Items.Clear;
//FIDList.Clear;
with pDataSet do
begin
First;
//以上是增加第一项
while not Eof do
begin
sCode:=Trim(FieldByName(Purviews.FModuleCode_FieldName).AsString);
sName:=Trim(FieldByName(Purviews.FModuleName_FieldName).AsString);
iLevel:=FieldByName(Purviews.FModuleLevel_FieldName).AsInteger;
if iLevel=1 then//确保代码符合标准
begin
MyNode[iLevel]:=ckTreePurview.Items.AddChild(nil,sName);
end
else
begin
MyNode[iLevel]:=ckTreePurview.Items.AddChild(MyNode[iLevel-1],sName);
end;
//MyNode[iLevel].ImageIndex:=iLevel;
//MyNode[iLevel].SelectedIndex:=iLevel-1;
Next;
end;
First;
end;
Screen.Cursor:=crDefault;
end;

读书人网 >.NET

热点推荐