Salvo il codice precedente:
Public Class Form1
Dim nodeArray(366) As Nodo
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
createItem("abc")
createItem("fds")
createItem("ghr")
createItem("uyj")
createItem("jhk")
createItem("fgh")
elenca()
End Sub
Sub createItem(stringa As String)
Dim hf As Integer = hashFunction(stringa)
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = New Nodo
nodeArray(hf).valore = stringa
nodeArray(hf).prossimo = Nothing
Else
Do
hf = hf + 1
If hf > UBound(nodeArray) Then Exit Do
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = New Nodo
nodeArray(hf).valore = stringa
nodeArray(hf).prossimo = Nothing
Exit Do
End If
Loop
End If
End Sub
Sub elenca()
For n = 0 To UBound(nodeArray)
If nodeArray(n) Is Nothing Then
Debug.Print(n & "---")
Else
Debug.Print(n & "---" & nodeArray(n).valore)
End If
Next
End Sub
Function hashFunction(stringa As String) As Integer
Dim asciValue As Integer = 0
For n = 1 To Len(stringa)
asciValue += Asc(Mid(stringa, n, 1))
Next
Return asciValue
End Function
End Class
Class Nodo
Public valore As String
Public prossimo As Nodo
End Class
E ora provo...
Ci vuole sempre una funzione Hash, che può essere anche quella che ho già usato:
Function hashFunction(stringa As String) As Integer
Dim asciValue As Integer = 0
For n = 1 To Len(stringa)
asciValue += Asc(Mid(stringa, n, 1))
Next
Return asciValue
End Function
End Class
In base a questa, ora, devo modificare questa:
Sub createItem(stringa As String)
Dim hf As Integer = hashFunction(stringa)
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = New Nodo
nodeArray(hf).valore = stringa
nodeArray(hf).prossimo = Nothing
Else
Do
hf = hf + 1
If hf > UBound(nodeArray) Then Exit Do
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = New Nodo
nodeArray(hf).valore = stringa
nodeArray(hf).prossimo = Nothing
Exit Do
End If
Loop
End If
End Sub
In base alla funzione hashFunction, dovrei piazzare il valore nel nodo adeguato:
Sub createItem(stringa As String)
Dim hf As Integer = hashFunction(stringa)
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = New Nodo
nodeArray(hf).valore = stringa
nodeArray(hf).prossimo = Nothing
End If
End Sub
Sub elenca()
For n = 0 To UBound(nodeArray)
If nodeArray(n) Is Nothing Then
Debug.Print(n & "---")
Else
Debug.Print(n & "---" & nodeArray(n).valore)
End If
Next
End Sub
Tutto come prima: vediamo cosa succede.
294---abc 309---fgh 317---fds 321---ghr 344---uyjConfrontando con il codice:
createItem("abc")
createItem("fds")
createItem("ghr")
createItem("uyj")
createItem("jhk")
createItem("fgh")
Anche qui c'è la stessa collisione: la funzione hashFunction restituisce 317 per "fds" e per "jhk", che però trovando il posto già occupato non viene inserita nella tabella.
Ora dobbiamo gestire però la creazione di liste concatenate per poter piazzare anche questo valore.
Dovrebbe cominciare dalla funzione createItem...
Se il nodo è già occupato va creato un altro nodo e impostato come "prossimo" del primo.
Ecco trovata la soluzione:
Public Class Form1
Dim nodeArray(366) As Nodo
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
createItem("abc")
createItem("fds")
createItem("ghr")
createItem("uyj")
createItem("jhk")
createItem("fgh")
elenca()
End Sub
Sub createItem(stringa As String)
Dim hf As Integer = hashFunction(stringa)
Dim tail As Nodo, temp As Nodo
'se il nodo base non è istanziato, si istanzia e gli si dà il valore.
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = New Nodo
nodeArray(hf).valore = stringa
nodeArray(hf).prossimo = Nothing
Else
'se il nodo base è istanziato, si dà al nodo base istanziato il nome tail (in quanto è la coda della fila)
tail = nodeArray(hf)
Do
'se non esiste un nodo prossimo al nodo tail... si istanzia un nuovo nodo chiamato temp...
If tail.prossimo Is Nothing Then
temp = New Nodo
'e gli si danno i valori.
temp.valore = stringa
temp.prossimo = Nothing
'si pone questo nodo temp appena istanziato come prossimo rispetto al nodo tail
tail.prossimo = temp
'si dà a questo nuovo nodo il nome di tail.
tail = temp
Exit Do
Else
'se invece esiste il nodo prossimo, allora questo diventerà il nuovo tail.
tail.prossimo = tail
End If
Loop
End If
End Sub
Sub elenca()
For n = 0 To UBound(nodeArray)
'se il nodo non è istanziato si scriverà solo il numero
If nodeArray(n) Is Nothing Then
Debug.Print(n & "---")
Else
'se il nodo è istanziato, si scriverà il valore
Debug.Print(n & "---" & nodeArray(n).valore)
'e bisogna cercare se ci sono altri nodi nella linked list
Dim tail As Nodo
tail = nodeArray(n)
Do
If Not tail.prossimo Is Nothing Then
tail = tail.prossimo
Debug.Print(n & "---" & tail.valore)
Else
Exit Do
End If
Loop
End If
Next
End Sub
Function hashFunction(stringa As String) As Integer
Dim asciValue As Integer = 0
For n = 1 To Len(stringa)
asciValue += Asc(Mid(stringa, n, 1))
Next
Return asciValue
End Function
End Class
Class Nodo
Public valore As String
Public prossimo As Nodo
End Class
Ed ecco i due valori che erano entrati in collisione, rappresentati su un'unica colonna con gli altri (non ho voluto cimentarmi per una rappresentazione migliore)
294---abc
309---fgh
317---fds
317---jhk
321---ghr
344---uyj
Confronto:
createItem("abc")
createItem("fds")
createItem("ghr")
createItem("uyj")
createItem("jhk")
createItem("fgh")
Perfetto! I due elementi appaiono con lo stesso numero in quanto sono parte di una lista concatenata.Ora creo intenzionalmente altri elementi il cui risultato della funzione hashFunction sia 317 e vediamo...
createItem("abc")
createItem("fds")
createItem("ghr")
createItem("uyj")
createItem("jhk")
createItem("fgh")
createItem("ddu")
createItem("dax")
createItem("uce")
E scopro che il programma si blocca.Dopo qualche incazzatura, trovo la fonte dell'errore.
Sub createItem(stringa As String)
Dim hf As Integer = hashFunction(stringa)
Dim tail As Nodo, temp As Nodo
temp = New Nodo
temp.valore = stringa
temp.prossimo = Nothing
'se il nodo base non è istanziato, si istanzia e gli si dà il valore.
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = temp
Else
'se il nodo base è istanziato, si dà al nodo base istanziato il nome tail (in quanto è la coda della fila)
tail = nodeArray(hf)
Do
'se non esiste un nodo prossimo al nodo tail... si istanzia un nuovo nodo chiamato temp...
If tail.prossimo Is Nothing Then
tail.prossimo = temp
Exit Do
Else
'se invece esiste il nodo prossimo, allora questo diventerà il nuovo tail.
tail.prossimo = tail
End If
Loop
End If
End Sub
Una volta che il programma vede che un nodo è stato già istanziato, deve ripetere il ciclo usando questo come nodo tail, ma tail.prossimo = tail non attribuisce il nome tail al prossimo nodo, ma fa diventare il nodo successivo uguale a quello che attualmente è tail.
Correggendo l'errore, il problema si risolve (ho impostato come oggetto iniziale sub Main credendo erroneamente che il pfoblema stesse nel caricamento del form ma va bene lo stesso).
Module Module1
Dim nodeArray(366) As Nodo
Sub main()
createItem("abc")
createItem("fds")
createItem("ghr")
createItem("uyj")
createItem("jhk")
createItem("fgh")
createItem("ddu")
createItem("dax")
createItem("uce")
elenca()
End Sub
Sub createItem(stringa As String)
Dim hf As Integer = hashFunction(stringa)
Dim tail As Nodo, temp As Nodo
temp = New Nodo
temp.valore = stringa
temp.prossimo = Nothing
'se il nodo base non è istanziato, si istanzia e gli si dà il valore.
If nodeArray(hf) Is Nothing Then
nodeArray(hf) = temp
Else
'se il nodo base è istanziato, si dà al nodo base istanziato il nome tail (in quanto è la coda della fila)
tail = nodeArray(hf)
Do
'se non esiste un nodo prossimo al nodo tail... si istanzia un nuovo nodo chiamato temp...
If tail.prossimo Is Nothing Then
tail.prossimo = temp
Exit Do
Else
'se invece esiste il nodo prossimo, allora questo diventerà il nuovo tail.
tail = tail.prossimo
End If
Loop
End If
End Sub
Sub elenca()
For n = 0 To UBound(nodeArray)
'se il nodo non è istanziato si scriverà solo il numero
If nodeArray(n) Is Nothing Then
Debug.Print(n & "---")
Else
'se il nodo è istanziato, si scriverà il valore
Debug.Print(n & "---" & nodeArray(n).valore)
'e bisogna cercare se ci sono altri nodi nella linked list
Dim tail As Nodo
tail = nodeArray(n)
Do
If Not tail.prossimo Is Nothing Then
tail = tail.prossimo
Debug.Print(n & "---" & tail.valore)
Else
Exit Do
End If
Loop
End If
Next
End Sub
Function hashFunction(stringa As String) As Integer
Dim asciValue As Integer = 0
For n = 1 To Len(stringa)
asciValue += Asc(Mid(stringa, n, 1))
Next
Return asciValue
End Function
Class Nodo
Public valore As String
Public prossimo As Nodo
End Class
End Module
Vediamo:
294---abc
309---fgh
317---fds
317---jhk
317---ddu
317---dax
317---uce
321---ghr
344---uyj
Mi sembra perfetto! Tutti quelli marcati in rosso fanno parte della linked list creata per risolvere il problema della collisione!
Nessun commento:
Posta un commento