Sortowanie przez scalanie VB.NET (VB 2010)

0

Witam,
napisałem algorytm sortowania przez scalanie w Visual Basic, jednak pojawia się błąd StackOverFlow Exception
Nie potrafię znaleźć błędu. Będę wdzięczny za pomoc. Dziękuję.

Module Module1
    Dim n As Integer = 19
 
    Sub generujtab(ByRef tab() As Integer)
        Randomize()
        Dim i As Integer = 0
        For i = 0 To n
            tab(i) = CInt(((100 * Rnd()) - 1))
        Next
 
    End Sub
 
    Sub wyswietl(ByVal tab() As Integer)
        Dim i As Integer
 
        For i = 0 To n
            Console.Write(CStr(tab(i)) + " ")
        Next
 
    End Sub
    Sub merge(ByRef tab() As Integer, ByVal p As Integer, ByVal mid As Integer, ByVal k As Integer)
        Dim tab2(n) As Integer
        Dim i As Integer
        Dim p1, p2, k1, k2 As Integer
        p1 = p
        p2 = mid + 1
        k1 = mid
        k2 = k
        i = p1
 
 
        Do While (p1 <= k1) And (p2 <= k2)
            If tab(p1) < tab(p2) Then
                tab2(i) = tab(p1)
                p1 += 1
            ElseIf tab(p1) > tab(p2) Then
                tab2(i) = tab(p2)
                p2 += 1
            End If
            i += 1
        Loop
 
        Do While p1 <= k1
            tab2(i) = tab(p1)
            p1 += 1
            i += 1
        Loop
 
        Do While p2 <= k2
            tab2(i) = tab(p2)
            p2 += 1
            i += i
        Loop
 
 
        For i = p To k
            tab(i) = tab2(i)
        Next
    End Sub
 
    Sub mergesort(ByRef tab() As Integer, ByVal p As Integer, ByVal k As Integer)
        Dim q As Integer
 
        If p < k Then
            q = CInt((p + k) / 2)
            mergesort(tab, p, q)
            mergesort(tab, q + 1, k)
            merge(tab, p, q, k)
 
        End If
 
    End Sub
 
    Sub main()
        Dim tab(n) As Integer
 
        generujtab(tab)
        wyswietl(tab)
        Console.WriteLine()
        mergesort(tab, 0, n)
        wyswietl(tab)
 
        Console.Read()
 
    End Sub
End Module
 
1
        Do While (p1 <= k1) And (p2 <= k2)
            If tab(p1) < tab(p2) Then
                tab2(i) = tab(p1)
                p1 += 1
            ElseIf tab(p1) > tab(p2) Then
                tab2(i) = tab(p2)
                p2 += 1
            End If
            i += 1
        Loop

a jeżeli tab(p1) = tab(p2) ?

        Do While p2 <= k2
            tab2(i) = tab(p2)
            p2 += 1
            i += i  <== podwajasz zmienną i ?!
        Loop

Jeżeli masz dużą tablicę to nic dziwnego, musisz mieć na stosie miejsca co najmniej Lon(n)n(rozmiar elementu tablicy) to nie licząc dużej ilości innych zmiennych których jest w nadmiarze.

0

Witam,
poprawiłem elementy, na które zwróciłeś uwagę :

Do While (p1 <= k1) And (p2 <= k2)
            If tab(p1) < tab(p2) Then
                tab2(i) = tab(p1)
                p1 += 1
           ** Else**
                tab2(i) = tab(p2)
                p2 += 1
            End If
            i += 1
        Loop 

oraz

Do While p2 <= k2
            tab2(i) = tab(p2)
            p2 += 1
           ** i += 1**
        Loop 

Jednak dalej pojawia się ten sam błąd. Tyle, że przy konkretnych okolicznościach.
Gdy tablica jest 7-mio elementowa lub mniejsza wszystko działa ok. Powyżej 7 elementów pojawia się StackOverFlow.
Sprawdziłem jak zmieniają się zmienne p i k w procedurze mergesort :

Sub mergesort(ByRef tab() As Integer, ByVal p As Integer, ByVal k As Integer)
        Dim q As Integer
        Console.WriteLine("--------------------------")
        Console.WriteLine("Dane mergesort przed if")
        Console.WriteLine("q:" & q)
        Console.WriteLine("p:" & p)
        Console.WriteLine("k:" & k)

        If p < k Then
            q = CInt((p + k) / 2)
            Console.WriteLine("--------------------------")
            Console.WriteLine("Dane mergesort po if")
            Console.WriteLine("q:" & q)
            Console.WriteLine("p:" & p)
            Console.WriteLine("k:" & k)
            'Console.WriteLine("margesort(" & tab & "," & p & "," & q)
            mergesort(tab, p, q)
            Console.WriteLine("--------------------------")
            Console.WriteLine("Dane mergesort po margesort(tab,p,q)")
            Console.WriteLine("q:" & q)
            Console.WriteLine("p:" & p)
            Console.WriteLine("k:" & k)
            mergesort(tab, q + 1, k)
            Console.WriteLine("--------------------------")
            Console.WriteLine("Dane mergesort po margesort(tab,q+1,k)")
            Console.WriteLine("q:" & q)
            Console.WriteLine("p:" & p)
            Console.WriteLine("k:" & k)
            merge(tab, p, q, k)
            Console.WriteLine("--------------------------")
            Console.WriteLine("Dane mergesort po marge(tab,p,q)")
            Console.WriteLine("q:" & q)
            Console.WriteLine("p:" & p)
            Console.WriteLine("k:" & k)

        End If 

Przy tablicy powyżej 7-miu elementów, po uporządkowaniu 3 elementów tablicy wartość p = 3 , k = 4 i procedura się zapętla w nieskończoność do StackOverFlow.
Nie rozumiem dlaczego.
I czemu zatem działa przy tablicach do 7 elementów?

0

Witam,

po analizie kilku przypadków, doszedłem do wniosku, że to linijka :

 q = CInt((p + k) / 2) 

wymaga zmiany.

No i zmieniłem zwykłe dzielnie / na \ - dzielenie całkowitoliczbowe.

 q = CInt((p + k) \ 2) 

I pomogło. Teraz nawet tablica 800000000 elementowa jest sortowana :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1