Здесь есть ряд мелких проблем и несколько больших возможностей. Вы сказали, что это ваша первая работа с VBA, так что простите, если я расскажу вам то, что вы уже знаете
Сначала мелочи:
Dim file, a, b, c As Integer
объявляет файлы a и b как варианты. Integer
- это 16-битный знак, поэтому может возникнуть риск переполнения, вместо него используйте Long
.
DIM
использование внутренних циклов неэффективно: в отличие от C ++ они не имеют циклической области.
Реальная возможность:
Используйте For Each
, где вы можете перебирать коллекции: это быстрее, чем индексирование.
На моем оборудовании ваш оригинальный код работал примерно через 160 секунд. Этот код примерно за 2,5 с (оба плюс время загрузки файла слов в коллекцию, около 4 с)
Sub build_trie()
Dim t1 As Long
Dim wd As Variant
Dim nd As Node
Set tree = New Node
' Dim file, a, b, c As Integer : declares file, a, b as variant
Dim file As Integer, a As Long, b As Long, c As Long ' Integer is 16 bit signed
Dim current As Node
Dim wordlist As Collection
Set wordlist = New Collection
file = FreeFile
Open "C:\corncob_caps.txt" For Input As file
' no point in doing inside loop, they are not scoped to the loop
Dim line As String
Dim match As Boolean
Dim char As String
Dim new_node As Node
Do While Not EOF(file)
'Dim line As String
Line Input #file, line
wordlist.Add line
Loop
t1 = GetTickCount
For Each wd In wordlist ' for each is faster
'For a = 1 To wordlist.Count
Set current = tree
For b = 1 To Len(wd)
'Dim match As Boolean
match = False
'Dim char As String
char = Mid$(wd, b, 1)
For Each nd In current.next_nodes
'For c = 1 To current.next_nodes.Count
If char = nd.letter Then
'If char = current.next_nodes.Item(c).letter Then
Set current = nd
'Set current = current.next_nodes.Item(c)
match = True
Exit For
End If
Next nd
If Not match Then
'Dim new_node As Node
Set new_node = New Node
new_node.letter = char
current.next_nodes.Add new_node
Set current = new_node
End If
Next b
current.is_word = True
Next wd
Debug.Print "Time = " & GetTickCount - t1 & " ms"
End Sub
EDIT:
загрузка списка слов в динамический массив сократит время загрузки до одной секунды. Имейте в виду, что Redim Preserve стоит дорого, поэтому делайте это кусками
Dim i As Long, sz As Long
sz = 10000
Dim wordlist() As String
ReDim wordlist(0 To sz)
file = FreeFile
Open "C:\corncob_caps.txt" For Input As file
i = 0
Do While Not EOF(file)
'Dim line As String
Line Input #file, line
wordlist(i) = line
i = i + 1
If i > sz Then
sz = sz + 10000
ReDim Preserve wordlist(0 To sz)
End If
'wordlist.Add line
Loop
ReDim Preserve wordlist(0 To i - 1)
затем переберите его как
For i = 0 To UBound(wordlist)
wd = wordlist(i)