Here you will find two VB.NET implementations of a merge sort. The first essentially takes the pseudocode described previously and puts it into VB.NET syntax. The second includes a considerable enhancement in terms of space and time usage, and therefore performance.
Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim myList(7) As Integer myList(0) = 66 myList(1) = 44 myList(2) = 63 myList(3) = 8 myList(4) = 10 myList(5) = 12 myList(6) = 144 myList(7) = 106 Dim Listout() As Integer Listout = MergeSort(myList) Dim stOut As String For i As Integer = 0 To UBound(Listout) stOut = stOut & Listout(i) & vbNewLine Next MsgBox(stOut, , “Merge Sorted List”) End Sub Function MergeSort(Arr() As Integer) As Integer() Dim ArrLeftHalf() As Integer Dim ArrRightHalf() As Integer If UBound(Arr) = 0 Then Return Arr Exit Function Else Call SplitList(Arr, ArrLeftHalf, ArrRightHalf) ArrLeftHalf = MergeSort(ArrLeftHalf) ArrRightHalf = MergeSort(ArrRightHalf) Return MergeTwoLists(ArrLeftHalf, ArrRightHalf) End If End Function Sub SplitList(Arr() As Integer, ByRef ArrLeft() As Integer, ByRef ArrRight() As Integer) 'Splits a list into two and returns the two resulting lists via parameters Dim iMiddle As Integer = Math.Floor((LBound(Arr) + UBound(Arr)) / 2) 'Populate empty list with left half of original list ReDim ArrLeft(iMiddle) For i As Integer = 0 To iMiddle ArrLeft(i) = Arr(i) Next 'Populate empty list with right half of original list Dim iFill As Integer ReDim ArrRight(UBound(Arr) – UBound(ArrLeft) – 1) For i As Integer = iMiddle + 1 To UBound(Arr) ArrRight(iFill) = Arr(i) iFill = iFill + 1 Next End Sub Function MergeTwoLists(Arr1() As Integer, Arr2() As Integer) As Integer() 'Merge two sorted lists into one sorted list Dim Arr3() As Integer ‘Source lists will be merged into new list Arr3 ReDim Arr3(UBound(Arr1) + UBound(Arr2) + 1) Dim Ptr1 As Integer Dim Ptr2 As Integer Dim Ptr3 As Integer 'Repeat until one of the arrays is exhausted Do While (Ptr3 <= UBound(Arr3)) And (Ptr1 <= UBound(Arr1)) And (Ptr2 <= UBound(Arr2)) If Arr1(Ptr1) < Arr2(Ptr2) Then Arr3(Ptr3) = Arr1(Ptr1) Ptr1 = Ptr1 + 1 Else Arr3(Ptr3) = Arr2(Ptr2) Ptr2 = Ptr2 + 1 End If Ptr3 = Ptr3 + 1 Loop 'Copy reamining items from larger of the source arrays into Arr3 If Ptr1 <= UBound(Arr1) Then 'still some items in Arr1 Do Until Ptr3 = UBound(Arr3) + 1 Arr3(Ptr3) = Arr1(Ptr1) Ptr1 = Ptr1 + 1 Ptr3 = Ptr3 + 1 Loop ElseIf Ptr2 <= UBound(Arr2) Then 'still some items in Arr2 Do Until Ptr3 = UBound(Arr3) + 1 Arr3(Ptr3) = Arr2(Ptr2) Ptr2 = Ptr2 + 1 Ptr3 = Ptr3 + 1 Loop End If Return Arr3 End Function End Class
Although the implementation above is indeed a working merge sort, there is something rather clumsy about it. The issue lies within the SplitList procedure. Whenever we split an array into two, that is, whenever we split a portion of the original array into two, we create two new arrays, and physically copy data into these two arrays. Then we merge pairs of temporary arrays to create yet another temporary array. Copying data around like this is an expensive process, particularly since we are doing it over and over and we don’t have any intention of hanging onto the intermediate arrays that are generated. Merge sort is often used to sort very large data sets, so we need to be mindful of how we use the memory. The fact is, we don’t ever realy need to split an array into two; we just need to achieve the effect of doing so. Our code just needs to look at the appropriate portion of the original array. This can be achieved by means of a few pointers.
Public Class Form1 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim myList(7) As Integer myList(0) = 66 myList(1) = 44 myList(2) = 63 myList(3) = 8 myList(4) = 10 myList(5) = 12 myList(6) = 144 myList(7) = 106 MergeSort(myList, LBound(myList), UBound(myList)) Dim stOut As String For i As Integer = 0 To UBound(myList) stOut = stOut & myList(i) & vbNewLine Next MsgBox(stOut, , “Merge Sorted List”) End Sub Function MergeSort(ByRef Arr As Integer(), iLow As Integer, iHigh As Integer) 'Pointers are then modified with successive calls, to redefine the portion being worked on. If iLow >= iHigh Then Return True Else Dim iMiddle As Integer = iLow + (iHigh – iLow) \ 2 Call MergeSort(Arr, iLow, iMiddle) 'left half is iLow to iMiddle Call MergeSort(Arr, iMiddle + 1, iHigh) 'right half is iMiddle + 1 to iHigh Call Merge(Arr, iLow, iMiddle, iHigh) End If End Function Sub Merge(ByRef Arr As Integer(), iLow As Integer, iMiddle As Integer, iHigh As Integer) 'Performs a merge in place; original array is the target 'Values of iLow, iMiddle and iHigh define which two sections of the original to ‘merge’ Dim uLeft As Integer = iMiddle – iLow 'Calculate upper bound of left portion Dim uRight As Integer = iHigh – iMiddle – 1 'Calculate upper bound of right portion 'Set up temporary source arrays to merge together Dim ArrLeftHalf As Integer() Dim ArrRightHalf As Integer() ReDim ArrLeftHalf(iMiddle – iLow) ReDim ArrRightHalf(iHigh – iMiddle – 1) Dim Ptr1 As Integer, Ptr2 As Integer, Ptr3 As Integer 'Generate temporary left half For Ptr1 = 0 To uLeft ArrLeftHalf(Ptr1) = Arr(iLow + Ptr1) Next 'Generate temorary right half For Ptr2 = 0 To uRight ArrRightHalf(Ptr2) = Arr(iMiddle + 1 + Ptr2) Next Ptr1 = 0 Ptr2 = 0 Ptr3 = iLow 'scan target from a position that leaves sorted data in tact 'Repeat until one of the source arrays is exhausted While (Ptr1 <= uLeft) And (Ptr2 <= uRight) If ArrLeftHalf(Ptr1) < ArrRightHalf(Ptr2) Then Arr(Ptr3) = ArrLeftHalf(Ptr1) Ptr1 = Ptr1 + 1 Else Arr(Ptr3) = ArrRightHalf(Ptr2) Ptr2 = Ptr2 + 1 End If Ptr3 = Ptr3 + 1 End While 'Copy reamining items from larger of the source arrays into target array While Ptr1 <= uLeft 'still some items in the left half Arr(Ptr3) = ArrLeftHalf(Ptr1) Ptr1 = Ptr1 + 1 Ptr3 = Ptr3 + 1 End While While Ptr2 <= uRight 'still some items in the right half Arr(Ptr3) = ArrRightHalf(Ptr2) Ptr2 = Ptr2 + 1 Ptr3 = Ptr3 + 1 End While End Sub End Class