|
下面这段代码比较啰嗦,主要是数据初始化稍微麻烦点,我估计1万以内的顶点规模的速度是可以接受的,更大规模的会受字典对象影响了。
你这个题目可以锻炼两方面的内容了- Private Type VERTEX
- Name As String * 1
- Neibours As New Collection
- Linkable() As Boolean
- End Type
- Private Sub CountTriangles()
- Dim aInput, i%, j%, k%, nInd%, sPnt, aPnts, nPnt1, nPnt2
- Dim aVerts() As VERTEX, dPnts As Object
- Dim dLine As Object
- Dim dTris As Object, nCnt%
- Dim t#
- t = Timer
- ' 图 数据结构初始化
- aInput = Cells(2, 1).Resize(Cells(1, 1).End(xlDown).Row - 1, 1)
- nInd = 0
- Set dPnts = CreateObject("scripting.dictionary")
- Set dLine = CreateObject("scripting.dictionary")
- ReDim aVerts(1 To UBound(aInput) * 3)
- For i = 1 To UBound(aInput)
- aPnts = Split(aInput(i, 1), ",")
- For Each sPnt In aPnts
- If Not dPnts.exists(sPnt) Then
- nInd = nInd + 1
- dPnts(sPnt) = nInd
- If nInd > UBound(aVerts) Then
- ReDim Preserve aVerts(1 To nInd * 2)
- End If
- aVerts(nInd).Name = sPnt
- End If
- Next
- For nPnt1 = 0 To UBound(aPnts) - 2
- For nPnt2 = nPnt1 + 1 To UBound(aPnts) - 1
- For j = nPnt2 + 1 To UBound(aPnts)
- sPnt = Array(aPnts(nPnt1), aPnts(nPnt2), aPnts(j))
- dLine(sPnt(0) & sPnt(1) & sPnt(2)) = 1
- dLine(sPnt(0) & sPnt(2) & sPnt(1)) = 1
- dLine(sPnt(1) & sPnt(0) & sPnt(2)) = 1
- dLine(sPnt(1) & sPnt(2) & sPnt(0)) = 1
- dLine(sPnt(2) & sPnt(0) & sPnt(1)) = 1
- dLine(sPnt(2) & sPnt(1) & sPnt(0)) = 1
- Next
- Next
- Next
- Next
- ReDim Preserve aVerts(1 To nInd)
- For i = 1 To nInd
- ReDim aVerts(i).Linkable(1 To nInd)
- Next
- For i = 1 To UBound(aInput)
- aPnts = Split(aInput(i, 1), ",")
- For j = 0 To UBound(aPnts) - 1
- For k = j + 1 To UBound(aPnts)
- With aVerts(dPnts(aPnts(j)))
- .Neibours.Add dPnts(aPnts(k)), aPnts(k)
- .Linkable(dPnts(aPnts(k))) = True
- End With
- With aVerts(dPnts(aPnts(k)))
- .Neibours.Add dPnts(aPnts(j)), aPnts(j)
- .Linkable(dPnts(aPnts(j))) = True
- End With
- Next
- Next
- Next
- ' 遍历查找
- Set dTris = CreateObject("scripting.dictionary")
- nCnt = 0
- For i = 1 To nInd
- For Each nPnt1 In aVerts(i).Neibours
- For Each nPnt2 In aVerts(nPnt1).Neibours
- If aVerts(nPnt2).Linkable(i) Then
- aPnts = Array(aVerts(i).Name, aVerts(nPnt1).Name, aVerts(nPnt2).Name)
- If Not dLine.exists(Join(aPnts, "")) Then
- If Not dTris.exists(aPnts(0) & aPnts(1) & aPnts(2)) And _
- Not dTris.exists(aPnts(0) & aPnts(2) & aPnts(1)) And _
- Not dTris.exists(aPnts(1) & aPnts(0) & aPnts(2)) And _
- Not dTris.exists(aPnts(1) & aPnts(2) & aPnts(0)) And _
- Not dTris.exists(aPnts(2) & aPnts(0) & aPnts(1)) And _
- Not dTris.exists(aPnts(2) & aPnts(1) & aPnts(0)) Then
- nCnt = nCnt + 1
- dTris(Join(aPnts, "")) = nCnt
- End If
- End If
- End If
- Next
- Next
- Next
- ' 输出结果
- ReDim aInput(0 To dTris.Count, 0 To 0)
- aPnts = dTris.keys
- aInput(0, 0) = "共 " & dTris.Count & " 个三角形"
- For i = 0 To UBound(aPnts)
- aInput(i + 1, 0) = aPnts(i)
- Next
- Columns(3).ClearContents
- Cells(1, 3).Resize(dTris.Count + 1, 1) = aInput
- ' 清空内存
- dPnts.RemoveAll: Set dPnts = Nothing
- dLine.RemoveAll: Set dLine = Nothing
- dTris.RemoveAll: Set dTris = Nothing
- For i = 1 To UBound(aVerts)
- Set aVerts(i).Neibours = Nothing
- Erase aVerts(i).Linkable
- Next
- Erase aVerts
- Debug.Print Timer - t
- End Sub
复制代码 |
|