`

不用递归的TreeView构建方法(优化方案)

阅读更多

高效的TreeView构建方法

网上一直有朋友说.net上的TreeView不够快,而且也不方便。那么真实的情况是否如此呢。我做的一项目中需要一个快速的Tree,它的数据源是MS SQL,其对应表中记录的结构如下:

ID

FatherID

Title

0101

01

基本建设支出

010109

0101

其它基本建设支出

其特点是父节点的ID正好是当前记录ID的长度-2所截取的字符串

因此我写下了如下代码:

一、普通的方法

Private Function BuildENTree(ByVal ds As DataSet)

Dim rs As DataRowCollection

Dim r As DataRow

Dim ID As String

Dim FatherID As String

Dim Title As String

Dim fn As TreeNode

Dim node As TreeNode

rs = ds.Tables(0).Rows

BootNode = New TreeNode

BootNode.Text = "[0] 所有单位"

BootNode.Tag = "0" '根目录

treeEN.Nodes.Add(BootNode)

For Each r In rs

ID = DirectCast(r.Item(0), String).Trim 'CODE

FatherID = DirectCast(r.Item(1), String).Trim 'FATHERCODE

Title = "[" & ID & "] " & DirectCast(r.Item(2), String).Trim 'TITLE

'查找与父节点ID相同的节点

fn = FindNode(FatherID)

If fn Is Nothing Then

'没找到对应ID的节点

Else

node = New TreeNode

With node

.Tag = ID

.Text = Title

End With

fn.Nodes.Add(node)

End If

Next

BootNode.Expand()

End Function

'在指定的节点下查找ID相符节点

Private Function FindNode(ByVal n As TreeNode, ByVal ID As String) As TreeNode

Dim ns As TreeNodeCollection

Dim node As TreeNode

Dim Flag As Boolean

Dim strText As String

Dim ReturnNode As TreeNode

Flag = False

If n.Tag = ID Then

Return n

Else

'如果路径根本不相同则返回

If (ID.Length < DirectCast(n.Tag, String).Length) OrElse ((n.Tag <> "0") AndAlso (ID.Substring(0, n.Tag.Length) <> n.Tag)) Then

Return Nothing

End If

ns = n.Nodes

For Each node In ns

ReturnNode = FindNode(node, ID)

If ReturnNode Is Nothing Then

'do nothing

Else

Flag = True

Exit For

End If

Next

If Flag = True Then Return ReturnNode

End If

Return Nothing

End Function

以上的代码利用将当前字节点的ID值存储于Node的Tag中,然后从根目录开始进行遍历进行查找。运行后发现其效率极为低下。但是网上的代码大多如此。

有没有其它方法可以增快其运行速度呢。

神说:“算法要么以空间换时间,要么以时间换空间”。

在某个时候我于是顿悟了。我发现我可以.net提供的HashTable,这可是个好东东。

那么如何来使用它呢?

二、快速的方法

首先我们需要增加一个定义

Private FastHashTable As Hashtable

然后需要将BuildENTree来做点小调整

Private Function BuildENTree(ByVal ds As DataSet)

Dim rs As DataRowCollection

Dim r As DataRow

Dim ID As String

Dim FatherID As String

Dim Title As String

Dim fn As TreeNode

Dim node As TreeNode

rs = ds.Tables(0).Rows

BootNode = New TreeNode

BootNode.Text = "[0] 所有单位"

BootNode.Tag = "0" '根目录

treeEN.Nodes.Add(BootNode)

FastHashTable.Add("0", BootNode)

For Each r In rs

ID = DirectCast(r.Item(0), String).Trim 'CODE

FatherID = DirectCast(r.Item(1), String).Trim 'FATHERCODE

Title = "[" & ID & "] " & DirectCast(r.Item(2), String).Trim 'TITLE

'查找与父节点ID相同的节点

fn = FindNode(FatherID)

If fn Is Nothing Then

'没找到对应ID的节点

Else

node = New TreeNode

With node

.Tag = ID

.Text = Title

End With

fn.Nodes.Add(node)

FastHashTable.Add(ID, node)

End If

Next

BootNode.Expand()

End Function

从以上代码看出,我只是增加了两处黑体的代码,它的作用就是将新增的节点不仅存到TreeView中,还要存到FashHashTable中,其关键字是ID值,只要没有重复的ID,那么就可以使用。

接下来我们还需要对FindNode进行改变。

'新版的快速查找

Private Function FindNode(ByVal ID As String) As TreeNode

Return FastHashTable.Item(ID)

End Function

好了,现在还有一个工作要做,就是要将FastHashTable进行初使化,尽量将其初使化成与你将要构建的数据节点数相同,我这个系统中是3000个节点,因此我增加了以下一句:

FastHashTable = New Hashtable(3000) '数量

现在,这个树已经很快了。

三、后记

即使是在.net时代,数据结构对我们也是很有用的。今天就到这儿吧!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics