|
楼主 |
发表于 2014-11-21 14:58
|
显示全部楼层
本帖最后由 lee1892 于 2014-11-21 15:06 编辑
一个广度优先的遍历查找,利用队列来实现迭代计算:- Public Function LongestPath(ByVal strTree As String) As Long
- Dim nSize&, aData, aTree(), i&, aCnt&(), nA&, nB&, aTemp&()
- aData = Split(strTree, ";")
- nSize = CInt(aData(0)) ' 第一个元素为节点数量
- ReDim aTree(1 To nSize), aCnt(1 To nSize)
- For i = 1 To nSize
- ReDim aTemp(1 To nSize)
- aTree(i) = aTemp ' 建立复合数组
- Next
- For i = 1 To UBound(aData)
- nA = CInt(Split(aData(i), ",")(0)): nB = CInt(Split(aData(i), ",")(1))
- ' 相互连接的两节点的编号
- aCnt(nA) = aCnt(nA) + 1: aCnt(nB) = aCnt(nB) + 1
- ' 某节点的连接节点数量计数
- aTree(nA)(aCnt(nA)) = nB: aTree(nB)(aCnt(nB)) = nA
- ' 建立连接
- Next
- ReDim aTemp(1 To nSize) ' 临时数组重置用以记录节点到根节点的距离
- nA = BFS_Iterative(aTree, aCnt, 1, aTemp) ' 距离根节点 1# 最远的节点编号
- ReDim aTemp(1 To nSize) ' 重置临时数组
- nB = BFS_Iterative(aTree, aCnt, nA, aTemp) ' 距离根节点 nA 最远的节点编号
- LongestPath = aTemp(nB) ' 返回距离值
- Erase aTree: Erase aTemp: Erase aCnt: Erase aData
- End Function
- Private Function BFS_Iterative&(ByRef aTree(), ByRef aCnt&(), ByVal nInd&, ByRef aDist&())
- ' aTree:以元素下标为节点编号的数组,其元素为该节点所连接的节点编号的数组
- ' aCnt:以元素下标为节点编号的数组,其元素为该节点所连接的节点的数量
- ' nInd:当前遍历的起始节点编号
- ' aDist:以元素下标为节点编号的数组,其元素为该节点至起始节点的距离值
- ' 返回值:距离起始节点最远的节点编号
- Dim i&, nCurInd&, nMaxDist&, nMInd&
- Dim aPathed() As Boolean
- Dim cQue As New Collection
- ReDim aPathed(1 To UBound(aTree)) ' 记录某节点是否已经查找过
- aPathed(nInd) = True ' 起始节点设置为已查找过
- cQue.Add nInd ' 用 集合 模拟队列,添加起始节点进入队列
- While cQue.Count > 0 ' 当队列不为空时循环
- nCurInd = cQue(1) ' 当前节点为队列中的第一个节点
- cQue.Remove 1 ' 删除队列中的第一个节点
- aPathed(nCurInd) = True ' 设置当前节点为已查找过
- For i = 1 To aCnt(nCurInd) ' 遍历查找当前节点的连接节点
- If Not aPathed(aTree(nCurInd)(i)) Then ' 如果该连接节点未查找过,则
- cQue.Add aTree(nCurInd)(i) ' 将该连接节点添加到队列中
- aDist(aTree(nCurInd)(i)) = aDist(nCurInd) + 1 ' 该连接节点距起始节点的距离为当前节点的距离 + 1
- End If
- Next
- Wend
- ' 找到距离起始节点最远的节点编号
- For i = 1 To UBound(aDist)
- If aDist(i) > nMaxDist Then nMaxDist = aDist(i): nMInd = i
- Next
- BFS_Iterative = nMInd
- Set cQue = Nothing
- End Function
复制代码 |
|