Option Explicit Option Compare Binary Option Base 1 Public Type TRIAL nKEYS As Long nITS As Integer PT As Long TT As Long ST As Long End Type Public Const RAD = 1 Public Const TQK = 2 Public Const QUI = 3 Public Const MER = 4 Public Const HEA = 5 Public Const COM = 6 Public Const SHE = 7 Public Const INS = 8 Public Const SEL = 9 Public Const LNG = 1 Public Const DBL = 2 Public Const STR = 3 Public Const MinDbl = -1.7976931348623E+308 Public Const MaxDbl = 1.7976931348623E+308 Public Const MinLng = -2147483647 Public Const MaxLng = 2147483647 Public Const MinStr = " " Public Const MaxStr = "???????????????" Public TIMES(LNG To STR, RAD To SEL, 1 To 8) As TRIAL Public L0() As Long 'buffer for unsorted longs Public L1() As Long 'buffer for sorted longs Public L2() As Long 'extra buffer used by MergeSort Public D() As Double 'buffer for unsorted doubles Public pD0() As Long 'buffer for unsorted pointers to doubles Public S() As String 'buffer for unsorted strings Public pS0() As Long 'buffer for unsorted pointers to strings Public B() As Byte 'buffers used by TernaryQuickSort & MSDRadixSort Public pB() As Long Public P() As Long 'buffer used for sorted pointers Public RAW_LNGS As Range Public SORTED_LNGS As Range Public RAW_DBLS As Range Public SORTED_DBLS As Range Public RAW_STRS As Range Public SORTED_STRS As Range Public RESULTS As Range Public NAMES Public ROW As Integer Sub TrySorts() Dim NK Dim ITS Dim ITS2 Dim LEVEL As Integer Dim SORT As Integer Dim nKEYS As Long Dim nITS As Integer Dim nITS2 As Integer Dim T As Long Dim tL As Long Dim tD As Long Dim tS As Long Dim tB As Long Dim tL2 As Long Dim tD2 As Long Dim tS2 As Long Dim I As Integer NK = Array(150, 500, 1500, 5000, 15000, 50000, 150000, 500000) ITS = Array(3000, 1000, 300, 100, 30, 10, 3, 1) ITS2 = Array(2000, 200, 20, 2, 0, 0, 0, 0) NAMES = Array("RadixSort", "TernQuickSort", "QuickSort", "MergeSort", "HeapSort", "CombSort", "ShellSort", "InsertionSort", "SelectionSort") Say "Setting up ranges." Set RAW_LNGS = Cells(2, 1).Resize(50, 1) Set SORTED_LNGS = Cells(2, 2).Resize(50, 1) Set RAW_DBLS = Cells(2, 3).Resize(50, 1) Set SORTED_DBLS = Cells(2, 4).Resize(50, 1) Set RAW_STRS = Cells(2, 5).Resize(50, 1) Set SORTED_STRS = Cells(2, 6).Resize(50, 1) Set RESULTS = Cells(2, 8).Resize(1000, 8) RAW_LNGS.Clear SORTED_LNGS.Clear RAW_DBLS.Clear SORTED_DBLS.Clear RAW_STRS.Clear SORTED_STRS.Clear RESULTS.Clear Cells(1, 1).Value = "raw lngs" Cells(1, 2).Value = "sorted lngs" Cells(1, 3).Value = "raw dbls" Cells(1, 4).Value = "sorted dbls" Cells(1, 5).Value = "raw strs" Cells(1, 6).Value = "sorted strs" Cells(1, 8).Value = "sort" Cells(1, 9).Value = "type" Cells(1, 10).Value = "# of keys" Cells(1, 11).Value = "repeats" Cells(1, 12).Value = "prep time" Cells(1, 13).Value = "total time" Cells(1, 14).Value = "sort time" Cells(1, 15).Value = "time/rep" Say "Dimensioning arrays." ReDim L0(0 To 500001) ReDim L1(0 To 500001) ReDim L2(0 To 500001) ReDim D(0 To 500001) ReDim pD0(0 To 500001) ReDim S(0 To 500001) ReDim pS0(0 To 500001) ReDim B(0 To 5000001) ReDim pB(0 To 500001) ReDim P(0 To 500001) ROW = 1 For LEVEL = 4 To 8 Say "Level " & CStr(LEVEL) nKEYS = CLng(NK(LEVEL)) nITS = CInt(ITS(LEVEL)) nITS2 = CInt(ITS2(LEVEL)) Say "Measuring long prep times." GetRndLngs nKEYS, L0 ListLngs RAW_LNGS, L0, 50 ACopyL 1, nKEYS, L0, L1 T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 Next I tL = Timer - T T = Timer For I = 1 To nITS2 ACopyL 1, nKEYS, L0, L1 Next I tL2 = Timer - T Say "Measuring double prep times." GetRndDbls nKEYS, D, pD0 pListDbls RAW_DBLS, D, pD0, 50 ACopyL 1, nKEYS, pD0, P T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P Next I tD = Timer - T T = Timer For I = 1 To nITS2 ACopyL 1, nKEYS, pD0, P Next I tD2 = Timer - T Say "Measuring string prep times." GetRndStrs nKEYS, 10, S, pS0 pListStrs RAW_STRS, S, pS0, 50 ACopyL 1, nKEYS, pS0, P T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P Next I tS = Timer - T T = Timer For I = 1 To nITS2 ACopyL 1, nKEYS, pS0, P Next I tS2 = Timer - T Strs2Bytes S, 1, nKEYS, B, pB T = Timer For I = 1 To nITS Strs2Bytes S, 1, nKEYS, B, pB Next I tB = Timer - T For SORT = RAD To SEL Select Case SORT Case RAD RunSortB RAD, LEVEL, nKEYS, nITS, tB Case TQK RunSortB TQK, LEVEL, nKEYS, nITS, tB Case QUI RunSortL QUI, LEVEL, nKEYS, nITS, tL RunSortD QUI, LEVEL, nKEYS, nITS, tD RunSortS QUI, LEVEL, nKEYS, nITS, tS Case MER RunSortL MER, LEVEL, nKEYS, nITS, tL RunSortD MER, LEVEL, nKEYS, nITS, tD RunSortS MER, LEVEL, nKEYS, nITS, tS Case HEA RunSortL HEA, LEVEL, nKEYS, nITS, tL RunSortD HEA, LEVEL, nKEYS, nITS, tD RunSortS HEA, LEVEL, nKEYS, nITS, tS Case COM RunSortL COM, LEVEL, nKEYS, nITS, tL RunSortD COM, LEVEL, nKEYS, nITS, tD RunSortS COM, LEVEL, nKEYS, nITS, tS Case SHE RunSortL SHE, LEVEL, nKEYS, nITS, tL RunSortD SHE, LEVEL, nKEYS, nITS, tD RunSortS SHE, LEVEL, nKEYS, nITS, tS Case INS If LEVEL < 5 Then RunSortL INS, LEVEL, nKEYS, nITS2, tL2 RunSortD INS, LEVEL, nKEYS, nITS2, tD2 RunSortS INS, LEVEL, nKEYS, nITS2, tS2 End If Case SEL If LEVEL < 5 Then RunSortL SEL, LEVEL, nKEYS, nITS2, tL2 RunSortD SEL, LEVEL, nKEYS, nITS2, tD2 RunSortS SEL, LEVEL, nKEYS, nITS2, tS2 End If End Select Cells(2, 1).Resize(1000, 15).Select With Selection .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter End With Cells(ROW, 1).Select Next SORT ROW = ROW + 1 Say "Waiting for possible break." Beep WaitFor 5 Next LEVEL End Sub Sub WaitFor(NSECS As Long) Dim TZERO As Long TZERO = Timer Do While Timer < TZERO + NSECS DoEvents Loop End Sub Sub RunSortL(SORT As Integer, LEVEL As Integer, nKEYS As Long, nITS As Integer, PT As Long) Dim T As Long Dim I As Integer SORTED_LNGS.Clear Say NAMES(SORT) & " longs" Select Case SORT Case INS T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 InsertL 1, nKEYS, L1 Next I Case SEL T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 SelectionSortL 1, nKEYS, L1 Next I Case SHE T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 ShellSortL 1, nKEYS, L1 Next I Case COM T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 CombSortL 1, nKEYS, L1 Next I Case HEA T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 HeapSortL 1, nKEYS, L1 Next I Case MER T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 MergeSortL 1, nKEYS, L1, L2 Next I Case QUI T = Timer For I = 1 To nITS ACopyL 1, nKEYS, L0, L1 QuickSortL 1, nKEYS, L1 Next I End Select With TIMES(LNG, SORT, LEVEL) .nKEYS = nKEYS .nITS = nITS .PT = PT .TT = Timer - T .ST = .TT - .PT ListLngs SORTED_LNGS, L1, 50 RESULTS(ROW, 1).Value = NAMES(SORT) RESULTS(ROW, 2).Value = "long" RESULTS(ROW, 3).Value = nKEYS RESULTS(ROW, 4).Value = nITS RESULTS(ROW, 5).Value = .PT RESULTS(ROW, 6).Value = .TT RESULTS(ROW, 7).Value = .ST RESULTS(ROW, 8).Value = CDbl(.ST) / nITS End With ROW = ROW + 1 End Sub Sub RunSortD(SORT As Integer, LEVEL As Integer, nKEYS As Long, nITS As Integer, PT As Long) Dim T As Long Dim I As Integer SORTED_DBLS.Clear Say NAMES(SORT) & " doubles" Select Case SORT Case INS T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P pInsertD 1, nKEYS, D, P Next I Case SEL T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P pSelectionSortD 1, nKEYS, D, P Next I Case SHE T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P pShellSortD 1, nKEYS, D, P Next I Case COM T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P pCombSortD 1, nKEYS, D, P Next I Case HEA T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P pHeapSortD 1, nKEYS, D, P Next I Case MER T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P pMergeSortD 1, nKEYS, D, P, L2 Next I Case QUI T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pD0, P pQuickSortD 1, nKEYS, D, P Next I End Select With TIMES(DBL, SORT, LEVEL) .nKEYS = nKEYS .nITS = nITS .PT = PT .TT = Timer - T .ST = .TT - .PT pListDbls SORTED_DBLS, D, P, 50 RESULTS(ROW, 1).Value = NAMES(SORT) RESULTS(ROW, 2).Value = "double" RESULTS(ROW, 3).Value = nKEYS RESULTS(ROW, 4).Value = nITS RESULTS(ROW, 5).Value = .PT RESULTS(ROW, 6).Value = .TT RESULTS(ROW, 7).Value = .ST RESULTS(ROW, 8).Value = CDbl(.ST) / nITS End With ROW = ROW + 1 End Sub Sub RunSortS(SORT As Integer, LEVEL As Integer, nKEYS As Long, nITS As Integer, PT As Long) Dim T As Long Dim I As Integer SORTED_STRS.Clear Say NAMES(SORT) & " strings" Select Case SORT Case INS T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P pInsertS 1, nKEYS, S, P Next I Case SEL T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P pSelectionSortS 1, nKEYS, S, P Next I Case SHE T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P pShellSortS 1, nKEYS, S, P Next I Case COM T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P pCombSortS 1, nKEYS, S, P Next I Case HEA T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P pHeapSortS 1, nKEYS, S, P Next I Case MER T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P pMergeSortS 1, nKEYS, S, P, L2 Next I Case QUI T = Timer For I = 1 To nITS ACopyL 1, nKEYS, pS0, P pQuickSortS 1, nKEYS, S, P Next I End Select With TIMES(DBL, SORT, LEVEL) .nKEYS = nKEYS .nITS = nITS .PT = PT .TT = Timer - T .ST = .TT - .PT pListStrs SORTED_STRS, S, P, 50 RESULTS(ROW, 1).Value = NAMES(SORT) RESULTS(ROW, 2).Value = "string" RESULTS(ROW, 3).Value = nKEYS RESULTS(ROW, 4).Value = nITS RESULTS(ROW, 5).Value = .PT RESULTS(ROW, 6).Value = .TT RESULTS(ROW, 7).Value = .ST RESULTS(ROW, 8).Value = CDbl(.ST) / nITS End With ROW = ROW + 1 End Sub Sub RunSortB(SORT As Integer, LEVEL As Integer, nKEYS As Long, nITS As Integer, PT As Long) Dim T As Long Dim I As Integer SORTED_STRS.Clear Say NAMES(SORT) & " strings" Select Case SORT Case RAD T = Timer For I = 1 To nITS Strs2Bytes S, 1, nKEYS, B, pB pRadixSortS B, pB, nKEYS Next I Case TQK T = Timer For I = 1 To nITS Strs2Bytes S, 1, nKEYS, B, pB pTernaryQuickSortS 1, nKEYS, B, pB Next I End Select With TIMES(STR, SORT, LEVEL) .nKEYS = nKEYS .nITS = nITS .PT = PT .TT = Timer - T .ST = .TT - .PT pListBytes SORTED_STRS, B, pB, nKEYS, 50 RESULTS(ROW, 1).Value = NAMES(SORT) RESULTS(ROW, 2).Value = "string" RESULTS(ROW, 3).Value = nKEYS RESULTS(ROW, 4).Value = nITS RESULTS(ROW, 5).Value = .PT RESULTS(ROW, 6).Value = .TT RESULTS(ROW, 7).Value = .ST RESULTS(ROW, 8).Value = CDbl(.ST) / nITS End With ROW = ROW + 1 End Sub Sub Say(S As String) Application.DisplayStatusBar = True Application.StatusBar = S End Sub Sub LoadLngs(BLK As Range, A() As Long, N As Long) Dim ROW As Long Dim COL As Integer Dim V N = BLK.Columns.COUNT * BLK.Rows.COUNT If UBound(A) < N + 1 Then ReDim A(0 To N + 1) A(0) = MinLng N = 1 For COL = 1 To BLK.Columns.COUNT For ROW = 1 To BLK.Rows.COUNT V = BLK(ROW, COL).Value If Not IsEmpty(V) Then A(N) = CLng(V) N = N + 1 If N Mod 10000 = 0 Then Say CStr(N) & " longs loaded" End If Next ROW Next COL A(N) = MaxLng End Sub Sub ListLngs(BLK As Range, A() As Long, ByVal N As Long, Optional MAXROWS As Long = 50000, Optional MAXCOLS As Integer = 1) Dim I As Long Dim ROW As Long Dim COL As Integer For I = 1 To N ROW = I Mod MAXROWS If ROW = 0 Then ROW = MAXROWS ElseIf ROW = 1 Then COL = COL + 1 If COL > MAXCOLS Then Exit Sub End If BLK(ROW, COL).Value = A(I) If I Mod 10000 = 0 Then Say CStr(I) & " longs listed" Next I End Sub Sub LoadDbls(BLK As Range, A() As Double, P() As Long, N As Long) Dim ROW As Long Dim COL As Integer Dim V N = BLK.Columns.COUNT * BLK.Rows.COUNT If UBound(A) < N + 1 Then ReDim A(0 To N + 1) A(0) = MinDbl N = 1 For COL = 1 To BLK.Columns.COUNT For ROW = 1 To BLK.Rows.COUNT V = BLK(ROW, COL).Value If Not IsEmpty(V) Then A(N) = CDbl(V) P(N) = N N = N + 1 If N Mod 10000 = 0 Then Say CStr(N) & " doubles loaded" End If Next ROW Next COL A(N) = MaxDbl End Sub Sub pListDbls(BLK As Range, A() As Double, P() As Long, ByVal N As Long, Optional MAXROWS As Long = 50000, Optional MAXCOLS As Integer = 1) Dim I As Long Dim ROW As Long Dim COL As Integer For I = 1 To N ROW = I Mod MAXROWS If ROW = 0 Then ROW = MAXROWS ElseIf ROW = 1 Then COL = COL + 1 If COL > MAXCOLS Then Exit Sub End If BLK(ROW, COL).Value = A(P(I)) If I Mod 10000 = 0 Then Say CStr(I) & " doubles listed" Next I End Sub Sub LoadStrs(BLK As Range, A() As String, P() As Long, N As Long) Dim ROW As Long Dim COL As Integer Dim V N = BLK.Columns.COUNT * BLK.Rows.COUNT If UBound(A) < N + 1 Then ReDim A(0 To N + 1) A(0) = MinStr N = 1 For COL = 1 To BLK.Columns.COUNT For ROW = 1 To BLK.Rows.COUNT V = BLK(ROW, COL).Value If Not IsEmpty(V) Then A(N) = CStr(V) P(N) = N N = N + 1 If N Mod 10000 = 0 Then Say CStr(N) & " strings loaded" End If Next ROW Next COL A(N) = MaxStr End Sub Sub pListStrs(BLK As Range, A() As String, P() As Long, ByVal N As Long, Optional MAXROWS As Long = 50000, Optional MAXCOLS As Integer = 1) Dim I As Long Dim ROW As Long Dim COL As Integer For I = 1 To N ROW = I Mod MAXROWS If ROW = 0 Then ROW = MAXROWS ElseIf ROW = 1 Then COL = COL + 1 If COL > MAXCOLS Then Exit Sub End If BLK(ROW, COL).Value = A(P(I)) If I Mod 10000 = 0 Then Say CStr(I) & " strings listed" Next I End Sub Sub pListBytes(BLK As Range, B() As Byte, P() As Long, ByVal N As Long, Optional MAXROWS As Long = 50000, Optional MAXCOLS As Integer = 1) Dim I As Long Dim ROW As Long Dim COL As Integer Dim J As Long Dim S As String For I = 1 To N ROW = I Mod MAXROWS If ROW = 0 Then ROW = MAXROWS ElseIf ROW = 1 Then COL = COL + 1 If COL > MAXCOLS Then Exit Sub End If S = "" J = P(I) Do S = S & Chr(B(J)) J = J + 1 Loop Until B(J) = 0 BLK(ROW, COL).Value = S If I Mod 10000 = 0 Then Say CStr(I) & " strings listed" Next I End Sub Sub Strs2Bytes(A() As String, L As Long, R As Long, B() As Byte, P() As Long) Dim StrNum As Long Dim nPtrs As Long Dim nBytes As Long Dim DEPTH As Integer nBytes = 0 nPtrs = 0 For StrNum = L To R nBytes = nBytes + Strings.Len(A(StrNum)) + 1 nPtrs = nPtrs + 1 Next StrNum ReDim B(1 To nBytes) ReDim P(1 To nPtrs) nPtrs = 1 nBytes = 1 For StrNum = L To R P(nPtrs) = nBytes For DEPTH = 1 To Strings.Len(A(StrNum)) B(nBytes) = Asc(Strings.MID(A(StrNum), DEPTH, 1)) nBytes = nBytes + 1 Next DEPTH B(nBytes) = 0 nBytes = nBytes + 1 nPtrs = nPtrs + 1 If StrNum Mod 10000 = 0 Then Say CStr(StrNum) & " converted" Next StrNum End Sub Sub ACopyS(L As Long, R As Long, A() As String, B() As String) Dim I As Long For I = L To R B(I) = A(I) Next I End Sub Sub ACopyL(L As Long, R As Long, A() As Long, B() As Long) Dim I As Long For I = L To R B(I) = A(I) Next I End Sub Sub ACopyD(L As Long, R As Long, A() As Double, B() As Double) Dim I As Long For I = L To R B(I) = A(I) Next I End Sub Sub GetRndStrs(CNT As Long, LENGTH As Integer, A() As String, P() As Long) Dim I As Long Dim J As Integer Dim C As Integer Dim S As String Randomize ReDim A(0 To CNT + 1) For I = 1 To CNT S = "" For J = 1 To LENGTH C = (Rnd() * 2999) Mod 47 If C < 10 Then C = C + 48 ElseIf C = 46 Then C = 32 Else C = C + 55 End If If C > 90 Then If I < 1 Then Exit For Else S = S & Strings.Chr(C) End If Next J J = 1 While Strings.MID(S, J, 1) = " " J = J + 1 Wend A(I) = Strings.MID(S, J) P(I) = I If I Mod 1000 = 0 Then Say "GetRndStrs " & CStr(I) Next I End Sub Sub GetRndDbls(CNT As Long, A() As Double, P() As Long) Dim I As Long Dim D As Double Randomize ReDim A(0 To CNT + 1) For I = 1 To CNT D = CDbl(Exp(Rnd() * WorksheetFunction.LN(MaxDbl))) If Rnd < 0.5 Then A(I) = -D Else A(I) = D P(I) = I Next I End Sub Sub GetRndLngs(CNT As Long, A() As Long) Dim I As Long Dim L As Long Randomize ReDim A(0 To CNT + 1) For I = 1 To CNT L = CLng(Exp(Rnd() * WorksheetFunction.LN(MaxLng))) If Rnd < 0.5 Then A(I) = -L Else A(I) = L Next I End Sub