Probleme mit Mergesort

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    Probleme mit Mergesort

    Hallo zusammen,

    ich habe versucht Mergesort in Visual Basic zu programmieren, habe den Algorithmus soweit verstanden, nur scheitere ich an der Umsetzung in VB. (Programmiere noch nicht all zu lange :/ )
    Der rekursive Teil, in dem der Array bis zur Listenlänge von 1 aufgeteilt wird, funktioniert. Das Problem besteht in dem "merging" der einzelnen kleinen Listen..als Ausgabe erhalte ich ausschließlich Nullen.

    Mein Code sieht so aus:


    Visual Basic-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    3. Dim testA(8), output(8) As Integer
    4. testA(1) = 2
    5. testA(2) = 3
    6. testA(3) = 4
    7. testA(4) = 5 'Testarray
    8. testA(5) = 1
    9. testA(6) = 6
    10. testA(7) = 7
    11. testA(8) = 8
    12. output = Mergesort(testA)
    13. For i = 1 To testA.Length - 1
    14. ListBox1.Items.Add(output(i)) 'Ausgabe in Listbox
    15. Next
    16. End Sub
    17. Private Function Mergesort(ByVal m As Array) As Integer()
    18. Dim leftA((m.Length - 1) / 2), rightA((m.Length - 1) / 2) As Integer
    19. If m.Length - 1 <= 1 Then
    20. Return m 'Abbruch bei Listenlänge von 1
    21. Else
    22. For i = 1 To (m.Length - 1) / 2
    23. leftA(i) = m(i) 'Aufteilung des Arrays in linke (& rechte Liste)
    24. Next
    25. For i = (m.Length - 1) / 2 + 1 To m.Length - 1 'Aufteilung des Arrays in linke (& rechte Liste)
    26. rightA(i - ((m.Length - 1) / 2)) = m(i)
    27. Next
    28. leftA = Mergesort(leftA) 'Selbstaufruf bis Arraylänge = 1
    29. rightA = Mergesort(rightA)
    30. Return merge(leftA, rightA)
    31. End If
    32. End Function
    33. Private Function merge(ByVal x As Array, ByVal y As Array) As Integer()
    34. Dim leftA(x.Length - 1) As Integer
    35. Dim rightA(y.Length - 1) As Integer
    36. Dim sortedA(8) As Integer
    37. Dim pos As Integer = 1
    38. leftA = x
    39. rightA = y
    40. While leftA.Length - 1 > 0 And rightA.Length - 1 > 0 'Bei Arraylänge ab 1
    41. If leftA(1) <= rightA(1) Then 'wird sortiert (per "merging"),
    42. sortedA(pos) = leftA(1) 'der kleinere Wert in das neue Array hinzugefügt
    43. Dim tempArray(leftA.Length - 2) As Integer
    44. For i = 1 To leftA.Length - 2 'und aus dem vorherigen Array gelöscht und dieser wird "aufgeschoben"
    45. tempArray(i) = leftA(i + 1)
    46. Next
    47. ReDim Preserve leftA(leftA.Length - 2)
    48. leftA = tempArray
    49. Else
    50. sortedA(pos) = rightA(1) 'Else für den Fall, dass die andere Zahl kleiner ist
    51. End If
    52. pos += 1 'pos nimmt Werte an, die außerhalb der Arraylänge liegen, wieso? :s
    53. End While
    54. If leftA.Length - 1 > 0 Then '|
    55. For i = 1 To leftA.Length - 1 '|
    56. sortedA(pos) = leftA(i) '|
    57. Next '| Rest wird dem neuen Array hinzugefügt
    58. ElseIf rightA.Length - 1 > 0 Then '|
    59. For i = 1 To rightA.Length - 1 '|
    60. sortedA(pos) = rightA(i) '|
    61. Next
    62. End If
    63. pos += 1
    64. Return sortedA
    65. End Function
    66. End Class


    Über Hilfe jeglicher Art wäre ich sehr glücklich. :)
    Levyce
    Du machst mehere Sachen falsch. Zum beispiel startet ein array in Visual Basic mit 0, nicht mit 1. Bei der Array-Deklaration wird auch nicht die Größe, sondern der maximale Index (= Größe - 1) angegeben. Ferner kann man viele deiner Berechnungen vereinfachen. Die Merge methode soll eigentlich nur auf einem einzigen ausgabe-array arbeiten. siehe Code unten:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    3. Dim testA(8), output(8) As Integer
    4. testA(0) = 54
    5. testA(1) = 22
    6. testA(2) = 31
    7. testA(3) = 4
    8. testA(4) = 5 'Testarray
    9. testA(5) = 1
    10. testA(6) = 6
    11. testA(7) = 7
    12. testA(8) = 8
    13. output = Mergesort(testA)
    14. For i = 0 To testA.Length - 1
    15. ListBox1.Items.Add(output(i)) 'Ausgabe in Listbox
    16. Next
    17. End Sub
    18. Private Function Mergesort(ByVal m As Array) As Integer()
    19. Dim leftA((m.Length / 2.0) - 1) As Integer
    20. Dim rightA(m.Length - leftA.Length - 1) As Integer
    21. If m.Length <= 1 Then
    22. Return m 'Abbruch bei Listenlänge von 1 oder 0
    23. Else
    24. For i = 0 To leftA.Length - 1
    25. leftA(i) = m(i) 'Aufteilung des Arrays in linke (& rechte Liste)
    26. Next
    27. For i = 0 To rightA.Length - 1 'Aufteilung des Arrays in linke (& rechte Liste)
    28. rightA(i) = m(i + leftA.Length)
    29. Next
    30. leftA = Mergesort(leftA) 'Selbstaufruf bis Arraylänge = 1
    31. rightA = Mergesort(rightA)
    32. Return merge(leftA, rightA)
    33. End If
    34. End Function
    35. Private Function merge(ByVal x As Array, ByVal y As Array) As Integer()
    36. Dim result(x.Length + y.Length - 1) As Integer
    37. Dim i As Integer = 0
    38. Dim x_i As Integer = 0
    39. Dim y_i As Integer = 0
    40. While x_i < x.Length AndAlso y_i < y.Length
    41. If x(x_i) <= y(y_i) Then
    42. result(i) = x(x_i)
    43. x_i += 1
    44. Else
    45. result(i) = y(y_i)
    46. y_i += 1
    47. End If
    48. i += 1
    49. End While
    50. While x_i < x.Length
    51. result(i) = x(x_i)
    52. x_i += 1
    53. i += 1
    54. End While
    55. While y_i < y.Length
    56. result(i) = y(y_i)
    57. y_i += 1
    58. i += 1
    59. End While
    60. Return result
    61. End Function
    62. End Class
    @Levyce
    Ich würde Dir empfehlen, Option Strict auf On zu stellen.
    Visual Studio - Empfohlene Einstellungen
    Du übergibst überall die untypisierten Arrays als Parameter (gibst aber passenderweise die typisierten Arrays zurück).
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils