I've been trying to write up a Quicksort function in Visual Basic as practice. It was simple enough to do and it works fine for arrays that don't have the same number appearing twice. But as soon as that happens, the second iteration of the loop advancing the left pointer toward the right pointer gets stuck in an endless loop and I can't for the life of me figure out why that happens.
If anyone has an idea why it's stuck, I'd appreciate the help. Here's the code:
Public Function Partition(ByVal a As Integer(), ByVal left As Integer, ByVal right As Integer)
Dim temp As Integer
Do While left <> right
Do While (a(left) < a(right)) And (left <> right)
left = left + 1
Loop
temp = a(left)
a(left) = a(right)
a(right) = temp
Do While (a(left) < a(right)) And (left <> right)
right = right - 1
Loop
temp = a(left)
a(left) = a(right)
a(right) = temp
Loop
Return left
End Function
Sub QuickSort(ByVal a As Integer(), ByVal left As Integer, ByVal right As
Integer)
If left < right Then
Dim position As Integer = Partition(a, left, right)
QuickSort(a, left, position - 1)
QuickSort(a, position + 1, right)
End If
End Sub
It happens whenever a(left)
and a(right)
are the same. After you swap them, they are still the same so you swap again and again.
To avoid that situation you need to
1.Replace the loop below:
Do While (a(left) < a(right)) And (left <> right)
left = left + 1
Loop
with this:
Do While (a(left) <= a(right)) And (left <> right)
left = left + 1
Loop
in order to put the elements equal to the pivot, to its left side
2.Add a one-step progress after the second loop (but only for the case when the iterators do not point at the same element which implies end of partitioning):
Do While (a(left) < a(right)) And (left <> right)
right = right - 1
Loop
temp = a(left)
a(left) = a(right)
a(right) = temp
If left <> right
left = left + 1
End if
So the modified function looks like following:
Public Function Partition(ByVal a As Integer(), ByVal left As Integer, ByVal right As Integer)
Dim temp As Integer
Do While left <> right
Do While (a(left) <= a(right)) And (left <> right)
left = left + 1
Loop
temp = a(left)
a(left) = a(right)
a(right) = temp
Do While (a(left) < a(right)) And (left <> right)
right = right - 1
Loop
temp = a(left)
a(left) = a(right)
a(right) = temp
If left <> right
left = left + 1
End if
Loop
Return left
End Function
PS. It could be further optimized to avoid swapping equal elements or swapping the element with itself, I'll leave it for you