[Chia sẻ] Sắp xếp (sort) trong mảng 2 chiều (Array 2D) (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Maika8008

Thành viên gạo cội
Tham gia
12/6/20
Bài viết
4,765
Được thích
5,742
Donate (Momo)
Donate
Giới tính
Nam
Tôi nhớ trên GPE có code sort array đâu đó rồi nhưng quả thực là chức năng tìm kiếm trên GPE sao sao đó mà tôi không tài nào tìm được (!).
Nay tình cờ có được 1 cái Sub sắp xếp 1 cột tăng dần của mảng 2 chiều, tôi sửa lại thành Function và làm thêm 1 cái Function gọi cái kia để sắp xếp thêm cột thứ 2, chia sẻ cho ai đó cần.
(Function trước tôi để nguyên ghi chú của tác giả)
Rich (BB code):
Function QuickSortArrayF(ByRef SortArray As Variant, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0)
    On Error Resume Next

    'Sort a 2-Dimensional array

    ' SampleUsage: sort arrData by the contents of column 3
    '
    '   QuickSortArray arrData, , , 3

    '
    'Posted by Jim Rech 10/20/98 Excel.Programming

    'Modifications, Nigel Heffernan:

    '       ' Escape failed comparison with empty variant
    '       ' Defensive coding: check inputs

    Dim i As Long
    Dim j As Long
    Dim varMid As Variant
    Dim arrRowTemp As Variant
    Dim lngColTemp As Long

    If IsEmpty(SortArray) Then
        Exit Function
    End If
    If InStr(TypeName(SortArray), "()") < 1 Then  'IsArray() is somewhat broken: Look for brackets in the type name
        Exit Function
    End If
    If lngMin = -1 Then
        lngMin = LBound(SortArray, 1)
    End If
    If lngMax = -1 Then
        lngMax = UBound(SortArray, 1)
    End If
    If lngMin >= lngMax Then    ' no sorting required
        Exit Function
    End If

    i = lngMin
    j = lngMax
    
    varMid = Empty
    varMid = SortArray((lngMin + lngMax) \ 2, lngColumn)

    ' We  send 'Empty' and invalid data items to the end of the list:
    If IsObject(varMid) Then  ' note that we don't check isObject(SortArray(n)) - varMid *might* pick up a valid default member or property
        i = lngMax
        j = lngMin
    ElseIf IsEmpty(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf IsNull(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf varMid = "" Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) = vbError Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) > 17 Then
        i = lngMax
        j = lngMin
    End If

    While i <= j
        While SortArray(i, lngColumn) < varMid And i < lngMax
            i = i + 1
        Wend
        While varMid < SortArray(j, lngColumn) And j > lngMin
            j = j - 1
        Wend

        If i <= j Then
            ' Swap the rows
            ReDim arrRowTemp(LBound(SortArray, 2) To UBound(SortArray, 2))
            For lngColTemp = LBound(SortArray, 2) To UBound(SortArray, 2)
                arrRowTemp(lngColTemp) = SortArray(i, lngColTemp)
                SortArray(i, lngColTemp) = SortArray(j, lngColTemp)
                SortArray(j, lngColTemp) = arrRowTemp(lngColTemp)
            Next lngColTemp
            Erase arrRowTemp

            i = i + 1
            j = j - 1
        End If
    Wend

    If (lngMin < j) Then Call QuickSortArrayF(SortArray, lngMin, j, lngColumn)
    If (i < lngMax) Then Call QuickSortArrayF(SortArray, i, lngMax, lngColumn)
  
    QuickSortArrayF = SortArray
End Function

Function QuickSortArrayF2(ByRef SortArray As Variant, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0, Optional lngColumn2 As Long = 0)
Dim SortArr As Variant
Dim i As Long, j As Long, k As Long, d As Long, r As Long
    If lngColumn = 0 Then lngColumn = 1
    SortArray = QuickSortArrayF(SortArray, , , lngColumn)
    ReDim TempArray(1 To UBound(SortArray, 1), 1 To UBound(SortArray, 2))
    For i = LBound(SortArray, 1) To UBound(SortArray, 1)
        k = k + 1
        On Error Resume Next
        If SortArray(i, lngColumn) <> SortArray(i + 1, lngColumn) Then
            If Err.Number = 9 Then
                On Error GoTo 0
                GoTo Sort
            End If
Sort:       If k > 1 Then
                ReDim SortArr(1 To k, 1 To UBound(SortArray, 2))
                For r = 1 To k
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArr(r, j) = SortArray(i - k + r, j)
                    Next
                Next
                SortArr = QuickSortArrayF(SortArr, , , lngColumn2)
                For d = i - k + 1 To i
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArray(d, j) = SortArr(d + k - i, j)
                    Next
                Next
                k = 0
            Else
                k = 0
            End If
        End If
    Next
    QuickSortArrayF2 = SortArray
End Function
 
Lần chỉnh sửa cuối:
Tôi nhớ trên GPE có code sort array đâu đó rồi nhưng quả thực là chức năng tìm kiếm trên GPE sao sao đó mà tôi không tài nào tìm được (!).
Nay tình cờ có được 1 cái Sub sắp xếp 1 cột tăng dần của mảng 2 chiều, tôi sửa lại thành Function và làm thêm 1 cái Function gọi cái kia để sắp xếp thêm cột thứ 2, chia sẻ cho ai đó cần.
(Function trước tôi để nguyên ghi chú của tác giả)
Rich (BB code):
Function QuickSortArrayF(ByRef SortArray As Variant, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0)
    On Error Resume Next

    'Sort a 2-Dimensional array

    ' SampleUsage: sort arrData by the contents of column 3
    '
    '   QuickSortArray arrData, , , 3

    '
    'Posted by Jim Rech 10/20/98 Excel.Programming

    'Modifications, Nigel Heffernan:

    '       ' Escape failed comparison with empty variant
    '       ' Defensive coding: check inputs

    Dim i As Long
    Dim j As Long
    Dim varMid As Variant
    Dim arrRowTemp As Variant
    Dim lngColTemp As Long

    If IsEmpty(SortArray) Then
        Exit Function
    End If
    If InStr(TypeName(SortArray), "()") < 1 Then  'IsArray() is somewhat broken: Look for brackets in the type name
        Exit Function
    End If
    If lngMin = -1 Then
        lngMin = LBound(SortArray, 1)
    End If
    If lngMax = -1 Then
        lngMax = UBound(SortArray, 1)
    End If
    If lngMin >= lngMax Then    ' no sorting required
        Exit Function
    End If

    i = lngMin
    j = lngMax
    
    varMid = Empty
    varMid = SortArray((lngMin + lngMax) \ 2, lngColumn)

    ' We  send 'Empty' and invalid data items to the end of the list:
    If IsObject(varMid) Then  ' note that we don't check isObject(SortArray(n)) - varMid *might* pick up a valid default member or property
        i = lngMax
        j = lngMin
    ElseIf IsEmpty(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf IsNull(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf varMid = "" Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) = vbError Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) > 17 Then
        i = lngMax
        j = lngMin
    End If

    While i <= j
        While SortArray(i, lngColumn) < varMid And i < lngMax
            i = i + 1
        Wend
        While varMid < SortArray(j, lngColumn) And j > lngMin
            j = j - 1
        Wend

        If i <= j Then
            ' Swap the rows
            ReDim arrRowTemp(LBound(SortArray, 2) To UBound(SortArray, 2))
            For lngColTemp = LBound(SortArray, 2) To UBound(SortArray, 2)
                arrRowTemp(lngColTemp) = SortArray(i, lngColTemp)
                SortArray(i, lngColTemp) = SortArray(j, lngColTemp)
                SortArray(j, lngColTemp) = arrRowTemp(lngColTemp)
            Next lngColTemp
            Erase arrRowTemp

            i = i + 1
            j = j - 1
        End If
    Wend

    If (lngMin < j) Then Call QuickSortArrayF(SortArray, lngMin, j, lngColumn)
    If (i < lngMax) Then Call QuickSortArrayF(SortArray, i, lngMax, lngColumn)
  
    QuickSortArrayF = SortArray
End Function

Function QuickSortArrayF2(ByRef SortArray As Variant, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0, Optional lngColumn2 As Long = 0)
Dim SortArr As Variant
Dim i As Long, j As Long, k As Long, d As Long, r As Long
  
    SortArray = QuickSortArrayF(SortArray, , , lngColumn)
    ReDim TempArray(1 To UBound(SortArray, 1), 1 To UBound(SortArray, 2))
    For i = LBound(SortArray, 1) To UBound(SortArray, 1)
        k = k + 1
        On Error Resume Next
        If SortArray(i, lngColumn) <> SortArray(i + 1, lngColumn) Then
            If Err.Number = 9 Then
                On Error GoTo 0
                GoTo Sort
            End If
Sort:       If k > 1 Then
                ReDim SortArr(1 To k, 1 To UBound(SortArray, 2))
                For r = 1 To k
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArr(r, j) = SortArray(i - k + r, j)
                    Next
                Next
                SortArr = QuickSortArrayF(SortArr, , , lngColumn2)
                For d = i - k + 1 To i
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArray(d, j) = SortArr(d + k - i, j)
                    Next
                Next
                k = 0
            Else
                k = 0
            End If
        End If
    Next
    QuickSortArrayF2 = SortArray
End Function
Trước đây tôi cũng có tìm kiếm vấn đề này nhưng chưa xử lý được.
Bạn có thể cho ví dụ về cách sử dụng hàm này như thế nào được không?
Cảm ơn
 
Upvote 0
Tôi nhớ trên GPE có code sort array đâu đó rồi nhưng quả thực là chức năng tìm kiếm trên GPE sao sao đó mà tôi không tài nào tìm được (!).
Nay tình cờ có được 1 cái Sub sắp xếp 1 cột tăng dần của mảng 2 chiều, tôi sửa lại thành Function và làm thêm 1 cái Function gọi cái kia để sắp xếp thêm cột thứ 2, chia sẻ cho ai đó cần.
(Function trước tôi để nguyên ghi chú của tác giả)
Rich (BB code):
Function QuickSortArrayF(ByRef SortArray As Variant, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0)
    On Error Resume Next

    'Sort a 2-Dimensional array

    ' SampleUsage: sort arrData by the contents of column 3
    '
    '   QuickSortArray arrData, , , 3

    '
    'Posted by Jim Rech 10/20/98 Excel.Programming

    'Modifications, Nigel Heffernan:

    '       ' Escape failed comparison with empty variant
    '       ' Defensive coding: check inputs

    Dim i As Long
    Dim j As Long
    Dim varMid As Variant
    Dim arrRowTemp As Variant
    Dim lngColTemp As Long

    If IsEmpty(SortArray) Then
        Exit Function
    End If
    If InStr(TypeName(SortArray), "()") < 1 Then  'IsArray() is somewhat broken: Look for brackets in the type name
        Exit Function
    End If
    If lngMin = -1 Then
        lngMin = LBound(SortArray, 1)
    End If
    If lngMax = -1 Then
        lngMax = UBound(SortArray, 1)
    End If
    If lngMin >= lngMax Then    ' no sorting required
        Exit Function
    End If

    i = lngMin
    j = lngMax
    
    varMid = Empty
    varMid = SortArray((lngMin + lngMax) \ 2, lngColumn)

    ' We  send 'Empty' and invalid data items to the end of the list:
    If IsObject(varMid) Then  ' note that we don't check isObject(SortArray(n)) - varMid *might* pick up a valid default member or property
        i = lngMax
        j = lngMin
    ElseIf IsEmpty(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf IsNull(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf varMid = "" Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) = vbError Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) > 17 Then
        i = lngMax
        j = lngMin
    End If

    While i <= j
        While SortArray(i, lngColumn) < varMid And i < lngMax
            i = i + 1
        Wend
        While varMid < SortArray(j, lngColumn) And j > lngMin
            j = j - 1
        Wend

        If i <= j Then
            ' Swap the rows
            ReDim arrRowTemp(LBound(SortArray, 2) To UBound(SortArray, 2))
            For lngColTemp = LBound(SortArray, 2) To UBound(SortArray, 2)
                arrRowTemp(lngColTemp) = SortArray(i, lngColTemp)
                SortArray(i, lngColTemp) = SortArray(j, lngColTemp)
                SortArray(j, lngColTemp) = arrRowTemp(lngColTemp)
            Next lngColTemp
            Erase arrRowTemp

            i = i + 1
            j = j - 1
        End If
    Wend

    If (lngMin < j) Then Call QuickSortArrayF(SortArray, lngMin, j, lngColumn)
    If (i < lngMax) Then Call QuickSortArrayF(SortArray, i, lngMax, lngColumn)
  
    QuickSortArrayF = SortArray
End Function

Function QuickSortArrayF2(ByRef SortArray As Variant, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0, Optional lngColumn2 As Long = 0)
Dim SortArr As Variant
Dim i As Long, j As Long, k As Long, d As Long, r As Long
  
    SortArray = QuickSortArrayF(SortArray, , , lngColumn)
    ReDim TempArray(1 To UBound(SortArray, 1), 1 To UBound(SortArray, 2))
    For i = LBound(SortArray, 1) To UBound(SortArray, 1)
        k = k + 1
        On Error Resume Next
        If SortArray(i, lngColumn) <> SortArray(i + 1, lngColumn) Then
            If Err.Number = 9 Then
                On Error GoTo 0
                GoTo Sort
            End If
Sort:       If k > 1 Then
                ReDim SortArr(1 To k, 1 To UBound(SortArray, 2))
                For r = 1 To k
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArr(r, j) = SortArray(i - k + r, j)
                    Next
                Next
                SortArr = QuickSortArrayF(SortArr, , , lngColumn2)
                For d = i - k + 1 To i
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArray(d, j) = SortArr(d + k - i, j)
                    Next
                Next
                k = 0
            Else
                k = 0
            End If
        End If
    Next
    QuickSortArrayF2 = SortArray
End Function
Cho hỏi code này sort loại dữ liệu nào vậy bạn
 
Upvote 0
Trước đây tôi cũng có tìm kiếm vấn đề này nhưng chưa xử lý được.
Bạn có thể cho ví dụ về cách sử dụng hàm này như thế nào được không?
Cảm ơn
1/ QuickSortArrayF(YourArray, , ,Cột cần sort) => Bỏ qua lngMin, lngMax vì thường là sort toàn bộ các dòng trong mảng. Còn không thì chỉ định sort từ lngMin tới lngMax
2/ QuickSortArrayF(YourArray, , ,Cột cần sort1, Cột cần sort2)
Bài đã được tự động gộp:

Cho hỏi code này sort loại dữ liệu nào vậy bạn
Kiểu text, number hoặc date
 
Upvote 0

Maika8008

QuickSortArrayF2 gọi QuickSortArrayF trong vòng lặp là một 'cuộc chơi' sai lầm
Sửa QuickSortArrayF là được QuickSortArrayF2

Đây là công trình sửa code của tôi cách đây chắc 2 năm trước của tôi bác tham khảo:

JavaScript:
Private Sub ArrayQuickSort_test()
  Dim Arr, arr2, t As Double: t = Timer
  Dim bHorizontal As Boolean
  bHorizontal = False
  Arr = [F3:J7].value
  ArrayQuickSort2 Arr, 1, , bHorizontal, , , arr2
  [F10:J14].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSort2 Arr, 1, , bHorizontal, , , arr2
  [F16:K21].value = Arr
  '----------------------------

  Arr = [F3:J7].value
  ArrayQuickSort2 Arr, 1, True, bHorizontal, , , arr2
  [F23:J27].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSort2 Arr, 1, True, bHorizontal, , , arr2
  Debug.Print join(arr2, ",")
  [F29:K34].value = Arr
  Debug.Print Round(Timer - t, 5)
End Sub

Sub ArrayQuickSort(ByRef ArrayIn As Variant, _
                Optional lngIndex As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional bHorizontal As Boolean = False, _
                Optional LngMin As Long = -1, _
                Optional LngMax As Long = -1, _
                Optional ArraySwapped As Variant)
  On Error Resume Next
  Dim i As Long, J As Long, R As Long, v As Variant, t As Variant, s()
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  v = Empty
  If bHorizontal Then
    If LngMin = -1 Then LngMin = LBound(ArrayIn, 2)
    If LngMax = -1 Then LngMax = UBound(ArrayIn, 2)
    v = ArrayIn(lngIndex, (LngMin + LngMax) \ 2)
  Else
    If LngMin = -1 Then LngMin = LBound(ArrayIn, 1)
    If LngMax = -1 Then LngMax = UBound(ArrayIn, 1)
    v = ArrayIn((LngMin + LngMax) \ 2, lngIndex)
  End If

  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  Select Case True
  Case VBA.IsObject(v): i = LngMax: J = LngMin
  Case IsEmpty(v): i = LngMax: J = LngMin
  Case IsNull(v): i = LngMax: J = LngMin
  Case v = vbNullString: i = LngMax: J = LngMin
  Case VBA.VarType(v) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(v) > 17: i = LngMax: J = LngMin
  End Select
  If bHorizontal Then
    If bDescending Then
      While i <= J
        While ArrayIn(lngIndex, i) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i)
            ArrayIn(R, i) = ArrayIn(R, J)
            ArrayIn(R, J) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(lngIndex, i) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i)
            ArrayIn(R, i) = ArrayIn(R, J)
            ArrayIn(R, J) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  Else
    If bDescending Then
      While i <= J
        While ArrayIn(i, lngIndex) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R)
            ArrayIn(i, R) = ArrayIn(J, R)
            ArrayIn(J, R) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(i, lngIndex) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R)
            ArrayIn(i, R) = ArrayIn(J, R)
            ArrayIn(J, R) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  End If
  If (LngMin < J) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, LngMin, J, ArraySwapped)
  If (i < LngMax) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, i, LngMax, ArraySwapped)
End Sub
Sub ArrayQuickSort2(ByRef ArrayIn As Variant, _
                Optional lngIndex As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional bHorizontal As Boolean = False, _
                Optional LngMin As Long = -1, _
                Optional LngMax As Long = -1, _
                Optional ArraySwapped As Variant)
  On Error Resume Next
  Dim i As Long, J As Long, R As Long, c As Long, v As Variant, t As Variant, s()
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  v = Empty
  If bHorizontal Then
    c = LBound(ArrayIn, 2): R = UBound(ArrayIn, 2)
    If LngMin = -1 Then LngMin = c
    If LngMax = -1 Then LngMax = R
    v = ArrayIn(lngIndex, (LngMin + LngMax) \ 2)
  Else
    c = LBound(ArrayIn, 1): R = UBound(ArrayIn, 1)
    If LngMin = -1 Then LngMin = c
    If LngMax = -1 Then LngMax = R
    v = ArrayIn((LngMin + LngMax) \ 2, lngIndex)
  End If
  If VBA.InStr(TypeName(ArraySwapped), "()") < 1 Then
    ReDim s(c To R): For i = c To R: s(i) = i: Next
    ArraySwapped = s
  End If
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  Select Case True
  Case VBA.IsObject(v): i = LngMax: J = LngMin
  Case IsEmpty(v): i = LngMax: J = LngMin
  Case IsNull(v): i = LngMax: J = LngMin
  Case v = vbNullString: i = LngMax: J = LngMin
  Case VBA.VarType(v) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(v) > 17: i = LngMax: J = LngMin
  End Select
  If bHorizontal Then
    If bDescending Then
      While i <= J
        While ArrayIn(lngIndex, i) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i): ArrayIn(R, i) = ArrayIn(R, J): ArrayIn(R, J) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(lngIndex, i) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i): ArrayIn(R, i) = ArrayIn(R, J): ArrayIn(R, J) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  Else
    If bDescending Then
      While i <= J
        While ArrayIn(i, lngIndex) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R): ArrayIn(i, R) = ArrayIn(J, R): ArrayIn(J, R) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(i, lngIndex) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R): ArrayIn(i, R) = ArrayIn(J, R): ArrayIn(J, R) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  End If
  If (LngMin < J) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, LngMin, J, ArraySwapped)
  If (i < LngMax) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, i, LngMax, ArraySwapped)
End Sub
Private Sub ArrayQuickSortV_test()
  Dim Arr, t As Double: t = Timer
  Arr = [F3:J7].value
  ArrayQuickSortV Arr, 1
  [F10:J14].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSortV Arr, 1
  [F16:K21].value = Arr
  '----------------------------

  Arr = [F3:J7].value
  ArrayQuickSortV Arr, 1, True
  [F23:J27].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSortV Arr, 1, True
  [F29:K34].value = Arr
  Debug.Print Round(Timer - t, 5)
End Sub
Sub ArrayQuickSortV(ByRef ArrayIn As Variant, _
                Optional lngColumn As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional LngMin& = -1, _
                Optional LngMax& = -1)
  On Error Resume Next
  Dim i&, J&
  Dim varMid As Variant, Tmp As Variant, lngColTemp&
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  If LngMin = -1 Then LngMin = LBound(ArrayIn, 1)
  If LngMax = -1 Then LngMax = UBound(ArrayIn, 1)
  ' no sorting required
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  varMid = Empty
  varMid = ArrayIn((LngMin + LngMax) \ 2, lngColumn)
  Select Case True
  Case VBA.IsObject(varMid): i = LngMax: J = LngMin
  Case IsEmpty(varMid): i = LngMax: J = LngMin
  Case IsNull(varMid): i = LngMax: J = LngMin
  Case varMid = "": i = LngMax: J = LngMin
  Case VBA.VarType(varMid) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(varMid) > 17: i = LngMax: J = LngMin
  End Select
  If bDescending Then
    While i <= J
      While ArrayIn(i, lngColumn) > varMid And i < LngMax: i = i + 1: Wend
      While varMid > ArrayIn(J, lngColumn) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        For lngColTemp = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
          Tmp = ArrayIn(i, lngColTemp)
          ArrayIn(i, lngColTemp) = ArrayIn(J, lngColTemp)
          ArrayIn(J, lngColTemp) = Tmp
        Next lngColTemp
        i = i + 1: J = J - 1
      End If
    Wend
  Else
    While i <= J
      While ArrayIn(i, lngColumn) < varMid And i < LngMax: i = i + 1: Wend
      While varMid < ArrayIn(J, lngColumn) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        For lngColTemp = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
          Tmp = ArrayIn(i, lngColTemp)
          ArrayIn(i, lngColTemp) = ArrayIn(J, lngColTemp)
          ArrayIn(J, lngColTemp) = Tmp
        Next lngColTemp
        i = i + 1: J = J - 1
      End If
    Wend
  End If
  If (LngMin < J) Then Call ArrayQuickSortV(ArrayIn, lngColumn, bDescending, LngMin, J)
  If (i < LngMax) Then Call ArrayQuickSortV(ArrayIn, lngColumn, bDescending, i, LngMax)
End Sub
Sub ArrayQuickSortH(ByRef ArrayIn As Variant, _
                 Optional lngColumn& = 0, _
                 Optional bDescending As Boolean, _
                 Optional LngMin& = -1, _
                 Optional LngMax& = -1)
  On Error Resume Next
  Dim i&, J&
  Dim varMid As Variant, arrRowTemp As Variant
  Dim lngColTemp&
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  If LngMin = -1 Then LngMin = LBound(ArrayIn, 2)
  If LngMax = -1 Then LngMax = UBound(ArrayIn, 2)
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  varMid = Empty
  varMid = ArrayIn(lngColumn, (LngMin + LngMax) \ 2)
  Select Case True
  Case VBA.IsObject(varMid): i = LngMax: J = LngMin
  Case IsEmpty(varMid): i = LngMax: J = LngMin
  Case IsNull(varMid): i = LngMax: J = LngMin
  Case varMid = "": i = LngMax: J = LngMin
  Case VBA.VarType(varMid) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(varMid) > 17: i = LngMax: J = LngMin
  End Select
  If bDescending Then
    While i <= J
      While ArrayIn(lngColumn, i) > varMid And i < LngMax: i = i + 1: Wend
      While varMid > ArrayIn(lngColumn, J) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        ReDim arrRowTemp(LBound(ArrayIn, 1) To UBound(ArrayIn, 1))
        For lngColTemp = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
          arrRowTemp(lngColTemp) = ArrayIn(lngColTemp, i)
          ArrayIn(lngColTemp, i) = ArrayIn(lngColTemp, J)
          ArrayIn(lngColTemp, J) = arrRowTemp(lngColTemp)
        Next lngColTemp
        Erase arrRowTemp
        i = i + 1: J = J - 1
      End If
    Wend
  Else
    While i <= J
      While ArrayIn(lngColumn, i) < varMid And i < LngMax: i = i + 1: Wend
      While varMid < ArrayIn(lngColumn, J) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        ReDim arrRowTemp(LBound(ArrayIn, 1) To UBound(ArrayIn, 1))
        For lngColTemp = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
          arrRowTemp(lngColTemp) = ArrayIn(lngColTemp, i)
          ArrayIn(lngColTemp, i) = ArrayIn(lngColTemp, J)
          ArrayIn(lngColTemp, J) = arrRowTemp(lngColTemp)
        Next lngColTemp
        Erase arrRowTemp
        i = i + 1: J = J - 1
      End If
    Wend
  End If
  If (LngMin < J) Then Call ArrayQuickSortH(ArrayIn, lngColumn, bDescending, LngMin, J)
  If (i < LngMax) Then Call ArrayQuickSortH(ArrayIn, lngColumn, bDescending, i, LngMax)
End Sub
 
Upvote 0

Maika8008

QuickSortArrayF2 gọi QuickSortArrayF trong vòng lặp là một 'cuộc chơi' sai lầm
Sửa QuickSortArrayF là được QuickSortArrayF2

Đây là công trình sửa code của tôi cách đây chắc 2 năm trước của tôi bác tham khảo:

JavaScript:
Private Sub ArrayQuickSort_test()
  Dim Arr, arr2, t As Double: t = Timer
  Dim bHorizontal As Boolean
  bHorizontal = False
  Arr = [F3:J7].value
  ArrayQuickSort2 Arr, 1, , bHorizontal, , , arr2
  [F10:J14].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSort2 Arr, 1, , bHorizontal, , , arr2
  [F16:K21].value = Arr
  '----------------------------

  Arr = [F3:J7].value
  ArrayQuickSort2 Arr, 1, True, bHorizontal, , , arr2
  [F23:J27].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSort2 Arr, 1, True, bHorizontal, , , arr2
  Debug.Print join(arr2, ",")
  [F29:K34].value = Arr
  Debug.Print Round(Timer - t, 5)
End Sub

Sub ArrayQuickSort(ByRef ArrayIn As Variant, _
                Optional lngIndex As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional bHorizontal As Boolean = False, _
                Optional LngMin As Long = -1, _
                Optional LngMax As Long = -1, _
                Optional ArraySwapped As Variant)
  On Error Resume Next
  Dim i As Long, J As Long, R As Long, v As Variant, t As Variant, s()
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  v = Empty
  If bHorizontal Then
    If LngMin = -1 Then LngMin = LBound(ArrayIn, 2)
    If LngMax = -1 Then LngMax = UBound(ArrayIn, 2)
    v = ArrayIn(lngIndex, (LngMin + LngMax) \ 2)
  Else
    If LngMin = -1 Then LngMin = LBound(ArrayIn, 1)
    If LngMax = -1 Then LngMax = UBound(ArrayIn, 1)
    v = ArrayIn((LngMin + LngMax) \ 2, lngIndex)
  End If

  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  Select Case True
  Case VBA.IsObject(v): i = LngMax: J = LngMin
  Case IsEmpty(v): i = LngMax: J = LngMin
  Case IsNull(v): i = LngMax: J = LngMin
  Case v = vbNullString: i = LngMax: J = LngMin
  Case VBA.VarType(v) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(v) > 17: i = LngMax: J = LngMin
  End Select
  If bHorizontal Then
    If bDescending Then
      While i <= J
        While ArrayIn(lngIndex, i) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i)
            ArrayIn(R, i) = ArrayIn(R, J)
            ArrayIn(R, J) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(lngIndex, i) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i)
            ArrayIn(R, i) = ArrayIn(R, J)
            ArrayIn(R, J) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  Else
    If bDescending Then
      While i <= J
        While ArrayIn(i, lngIndex) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R)
            ArrayIn(i, R) = ArrayIn(J, R)
            ArrayIn(J, R) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(i, lngIndex) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R)
            ArrayIn(i, R) = ArrayIn(J, R)
            ArrayIn(J, R) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  End If
  If (LngMin < J) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, LngMin, J, ArraySwapped)
  If (i < LngMax) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, i, LngMax, ArraySwapped)
End Sub
Sub ArrayQuickSort2(ByRef ArrayIn As Variant, _
                Optional lngIndex As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional bHorizontal As Boolean = False, _
                Optional LngMin As Long = -1, _
                Optional LngMax As Long = -1, _
                Optional ArraySwapped As Variant)
  On Error Resume Next
  Dim i As Long, J As Long, R As Long, c As Long, v As Variant, t As Variant, s()
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  v = Empty
  If bHorizontal Then
    c = LBound(ArrayIn, 2): R = UBound(ArrayIn, 2)
    If LngMin = -1 Then LngMin = c
    If LngMax = -1 Then LngMax = R
    v = ArrayIn(lngIndex, (LngMin + LngMax) \ 2)
  Else
    c = LBound(ArrayIn, 1): R = UBound(ArrayIn, 1)
    If LngMin = -1 Then LngMin = c
    If LngMax = -1 Then LngMax = R
    v = ArrayIn((LngMin + LngMax) \ 2, lngIndex)
  End If
  If VBA.InStr(TypeName(ArraySwapped), "()") < 1 Then
    ReDim s(c To R): For i = c To R: s(i) = i: Next
    ArraySwapped = s
  End If
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  Select Case True
  Case VBA.IsObject(v): i = LngMax: J = LngMin
  Case IsEmpty(v): i = LngMax: J = LngMin
  Case IsNull(v): i = LngMax: J = LngMin
  Case v = vbNullString: i = LngMax: J = LngMin
  Case VBA.VarType(v) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(v) > 17: i = LngMax: J = LngMin
  End Select
  If bHorizontal Then
    If bDescending Then
      While i <= J
        While ArrayIn(lngIndex, i) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i): ArrayIn(R, i) = ArrayIn(R, J): ArrayIn(R, J) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(lngIndex, i) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i): ArrayIn(R, i) = ArrayIn(R, J): ArrayIn(R, J) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  Else
    If bDescending Then
      While i <= J
        While ArrayIn(i, lngIndex) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R): ArrayIn(i, R) = ArrayIn(J, R): ArrayIn(J, R) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(i, lngIndex) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R): ArrayIn(i, R) = ArrayIn(J, R): ArrayIn(J, R) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  End If
  If (LngMin < J) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, LngMin, J, ArraySwapped)
  If (i < LngMax) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, i, LngMax, ArraySwapped)
End Sub
Private Sub ArrayQuickSortV_test()
  Dim Arr, t As Double: t = Timer
  Arr = [F3:J7].value
  ArrayQuickSortV Arr, 1
  [F10:J14].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSortV Arr, 1
  [F16:K21].value = Arr
  '----------------------------

  Arr = [F3:J7].value
  ArrayQuickSortV Arr, 1, True
  [F23:J27].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSortV Arr, 1, True
  [F29:K34].value = Arr
  Debug.Print Round(Timer - t, 5)
End Sub
Sub ArrayQuickSortV(ByRef ArrayIn As Variant, _
                Optional lngColumn As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional LngMin& = -1, _
                Optional LngMax& = -1)
  On Error Resume Next
  Dim i&, J&
  Dim varMid As Variant, Tmp As Variant, lngColTemp&
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  If LngMin = -1 Then LngMin = LBound(ArrayIn, 1)
  If LngMax = -1 Then LngMax = UBound(ArrayIn, 1)
  ' no sorting required
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  varMid = Empty
  varMid = ArrayIn((LngMin + LngMax) \ 2, lngColumn)
  Select Case True
  Case VBA.IsObject(varMid): i = LngMax: J = LngMin
  Case IsEmpty(varMid): i = LngMax: J = LngMin
  Case IsNull(varMid): i = LngMax: J = LngMin
  Case varMid = "": i = LngMax: J = LngMin
  Case VBA.VarType(varMid) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(varMid) > 17: i = LngMax: J = LngMin
  End Select
  If bDescending Then
    While i <= J
      While ArrayIn(i, lngColumn) > varMid And i < LngMax: i = i + 1: Wend
      While varMid > ArrayIn(J, lngColumn) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        For lngColTemp = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
          Tmp = ArrayIn(i, lngColTemp)
          ArrayIn(i, lngColTemp) = ArrayIn(J, lngColTemp)
          ArrayIn(J, lngColTemp) = Tmp
        Next lngColTemp
        i = i + 1: J = J - 1
      End If
    Wend
  Else
    While i <= J
      While ArrayIn(i, lngColumn) < varMid And i < LngMax: i = i + 1: Wend
      While varMid < ArrayIn(J, lngColumn) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        For lngColTemp = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
          Tmp = ArrayIn(i, lngColTemp)
          ArrayIn(i, lngColTemp) = ArrayIn(J, lngColTemp)
          ArrayIn(J, lngColTemp) = Tmp
        Next lngColTemp
        i = i + 1: J = J - 1
      End If
    Wend
  End If
  If (LngMin < J) Then Call ArrayQuickSortV(ArrayIn, lngColumn, bDescending, LngMin, J)
  If (i < LngMax) Then Call ArrayQuickSortV(ArrayIn, lngColumn, bDescending, i, LngMax)
End Sub
Sub ArrayQuickSortH(ByRef ArrayIn As Variant, _
                 Optional lngColumn& = 0, _
                 Optional bDescending As Boolean, _
                 Optional LngMin& = -1, _
                 Optional LngMax& = -1)
  On Error Resume Next
  Dim i&, J&
  Dim varMid As Variant, arrRowTemp As Variant
  Dim lngColTemp&
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  If LngMin = -1 Then LngMin = LBound(ArrayIn, 2)
  If LngMax = -1 Then LngMax = UBound(ArrayIn, 2)
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  varMid = Empty
  varMid = ArrayIn(lngColumn, (LngMin + LngMax) \ 2)
  Select Case True
  Case VBA.IsObject(varMid): i = LngMax: J = LngMin
  Case IsEmpty(varMid): i = LngMax: J = LngMin
  Case IsNull(varMid): i = LngMax: J = LngMin
  Case varMid = "": i = LngMax: J = LngMin
  Case VBA.VarType(varMid) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(varMid) > 17: i = LngMax: J = LngMin
  End Select
  If bDescending Then
    While i <= J
      While ArrayIn(lngColumn, i) > varMid And i < LngMax: i = i + 1: Wend
      While varMid > ArrayIn(lngColumn, J) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        ReDim arrRowTemp(LBound(ArrayIn, 1) To UBound(ArrayIn, 1))
        For lngColTemp = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
          arrRowTemp(lngColTemp) = ArrayIn(lngColTemp, i)
          ArrayIn(lngColTemp, i) = ArrayIn(lngColTemp, J)
          ArrayIn(lngColTemp, J) = arrRowTemp(lngColTemp)
        Next lngColTemp
        Erase arrRowTemp
        i = i + 1: J = J - 1
      End If
    Wend
  Else
    While i <= J
      While ArrayIn(lngColumn, i) < varMid And i < LngMax: i = i + 1: Wend
      While varMid < ArrayIn(lngColumn, J) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        ReDim arrRowTemp(LBound(ArrayIn, 1) To UBound(ArrayIn, 1))
        For lngColTemp = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
          arrRowTemp(lngColTemp) = ArrayIn(lngColTemp, i)
          ArrayIn(lngColTemp, i) = ArrayIn(lngColTemp, J)
          ArrayIn(lngColTemp, J) = arrRowTemp(lngColTemp)
        Next lngColTemp
        Erase arrRowTemp
        i = i + 1: J = J - 1
      End If
    Wend
  End If
  If (LngMin < J) Then Call ArrayQuickSortH(ArrayIn, lngColumn, bDescending, LngMin, J)
  If (i < LngMax) Then Call ArrayQuickSortH(ArrayIn, lngColumn, bDescending, i, LngMax)
End Sub
Hihi. Tôi nghĩ được cách gì thì làm cách ấy thôi. Định sửa cái hàm đầu nhưng thấy dài dòng quá bèn gọi nó lên cho tiện.
 
Upvote 0

Maika8008

QuickSortArrayF2 gọi QuickSortArrayF trong vòng lặp là một 'cuộc chơi' sai lầm
Sửa QuickSortArrayF là được QuickSortArrayF2

Đây là công trình sửa code của tôi cách đây chắc 2 năm trước của tôi bác tham khảo:

JavaScript:
Private Sub ArrayQuickSort_test()
  Dim Arr, arr2, t As Double: t = Timer
  Dim bHorizontal As Boolean
  bHorizontal = False
  Arr = [F3:J7].value
  ArrayQuickSort2 Arr, 1, , bHorizontal, , , arr2
  [F10:J14].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSort2 Arr, 1, , bHorizontal, , , arr2
  [F16:K21].value = Arr
  '----------------------------

  Arr = [F3:J7].value
  ArrayQuickSort2 Arr, 1, True, bHorizontal, , , arr2
  [F23:J27].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSort2 Arr, 1, True, bHorizontal, , , arr2
  Debug.Print join(arr2, ",")
  [F29:K34].value = Arr
  Debug.Print Round(Timer - t, 5)
End Sub

Sub ArrayQuickSort(ByRef ArrayIn As Variant, _
                Optional lngIndex As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional bHorizontal As Boolean = False, _
                Optional LngMin As Long = -1, _
                Optional LngMax As Long = -1, _
                Optional ArraySwapped As Variant)
  On Error Resume Next
  Dim i As Long, J As Long, R As Long, v As Variant, t As Variant, s()
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  v = Empty
  If bHorizontal Then
    If LngMin = -1 Then LngMin = LBound(ArrayIn, 2)
    If LngMax = -1 Then LngMax = UBound(ArrayIn, 2)
    v = ArrayIn(lngIndex, (LngMin + LngMax) \ 2)
  Else
    If LngMin = -1 Then LngMin = LBound(ArrayIn, 1)
    If LngMax = -1 Then LngMax = UBound(ArrayIn, 1)
    v = ArrayIn((LngMin + LngMax) \ 2, lngIndex)
  End If

  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  Select Case True
  Case VBA.IsObject(v): i = LngMax: J = LngMin
  Case IsEmpty(v): i = LngMax: J = LngMin
  Case IsNull(v): i = LngMax: J = LngMin
  Case v = vbNullString: i = LngMax: J = LngMin
  Case VBA.VarType(v) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(v) > 17: i = LngMax: J = LngMin
  End Select
  If bHorizontal Then
    If bDescending Then
      While i <= J
        While ArrayIn(lngIndex, i) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i)
            ArrayIn(R, i) = ArrayIn(R, J)
            ArrayIn(R, J) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(lngIndex, i) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i)
            ArrayIn(R, i) = ArrayIn(R, J)
            ArrayIn(R, J) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  Else
    If bDescending Then
      While i <= J
        While ArrayIn(i, lngIndex) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R)
            ArrayIn(i, R) = ArrayIn(J, R)
            ArrayIn(J, R) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(i, lngIndex) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R)
            ArrayIn(i, R) = ArrayIn(J, R)
            ArrayIn(J, R) = t
          Next R
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  End If
  If (LngMin < J) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, LngMin, J, ArraySwapped)
  If (i < LngMax) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, i, LngMax, ArraySwapped)
End Sub
Sub ArrayQuickSort2(ByRef ArrayIn As Variant, _
                Optional lngIndex As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional bHorizontal As Boolean = False, _
                Optional LngMin As Long = -1, _
                Optional LngMax As Long = -1, _
                Optional ArraySwapped As Variant)
  On Error Resume Next
  Dim i As Long, J As Long, R As Long, c As Long, v As Variant, t As Variant, s()
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  v = Empty
  If bHorizontal Then
    c = LBound(ArrayIn, 2): R = UBound(ArrayIn, 2)
    If LngMin = -1 Then LngMin = c
    If LngMax = -1 Then LngMax = R
    v = ArrayIn(lngIndex, (LngMin + LngMax) \ 2)
  Else
    c = LBound(ArrayIn, 1): R = UBound(ArrayIn, 1)
    If LngMin = -1 Then LngMin = c
    If LngMax = -1 Then LngMax = R
    v = ArrayIn((LngMin + LngMax) \ 2, lngIndex)
  End If
  If VBA.InStr(TypeName(ArraySwapped), "()") < 1 Then
    ReDim s(c To R): For i = c To R: s(i) = i: Next
    ArraySwapped = s
  End If
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  Select Case True
  Case VBA.IsObject(v): i = LngMax: J = LngMin
  Case IsEmpty(v): i = LngMax: J = LngMin
  Case IsNull(v): i = LngMax: J = LngMin
  Case v = vbNullString: i = LngMax: J = LngMin
  Case VBA.VarType(v) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(v) > 17: i = LngMax: J = LngMin
  End Select
  If bHorizontal Then
    If bDescending Then
      While i <= J
        While ArrayIn(lngIndex, i) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i): ArrayIn(R, i) = ArrayIn(R, J): ArrayIn(R, J) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(lngIndex, i) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(lngIndex, J) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
            t = ArrayIn(R, i): ArrayIn(R, i) = ArrayIn(R, J): ArrayIn(R, J) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  Else
    If bDescending Then
      While i <= J
        While ArrayIn(i, lngIndex) > v And i < LngMax: i = i + 1: Wend
        While v > ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R): ArrayIn(i, R) = ArrayIn(J, R): ArrayIn(J, R) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    Else
      While i <= J
        While ArrayIn(i, lngIndex) < v And i < LngMax: i = i + 1: Wend
        While v < ArrayIn(J, lngIndex) And J > LngMin: J = J - 1: Wend
        If i <= J Then
          For R = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
            t = ArrayIn(i, R): ArrayIn(i, R) = ArrayIn(J, R): ArrayIn(J, R) = t
          Next R
          t = ArraySwapped(i): ArraySwapped(i) = ArraySwapped(J): ArraySwapped(J) = t
          i = i + 1: J = J - 1
        End If
      Wend
    End If
  End If
  If (LngMin < J) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, LngMin, J, ArraySwapped)
  If (i < LngMax) Then Call ArrayQuickSort(ArrayIn, lngIndex, bDescending, bHorizontal, i, LngMax, ArraySwapped)
End Sub
Private Sub ArrayQuickSortV_test()
  Dim Arr, t As Double: t = Timer
  Arr = [F3:J7].value
  ArrayQuickSortV Arr, 1
  [F10:J14].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSortV Arr, 1
  [F16:K21].value = Arr
  '----------------------------

  Arr = [F3:J7].value
  ArrayQuickSortV Arr, 1, True
  [F23:J27].value = Arr
  '----------------------------
  Arr = [F3:K8].value
  ArrayQuickSortV Arr, 1, True
  [F29:K34].value = Arr
  Debug.Print Round(Timer - t, 5)
End Sub
Sub ArrayQuickSortV(ByRef ArrayIn As Variant, _
                Optional lngColumn As Long = 0, _
                Optional bDescending As Boolean = False, _
                Optional LngMin& = -1, _
                Optional LngMax& = -1)
  On Error Resume Next
  Dim i&, J&
  Dim varMid As Variant, Tmp As Variant, lngColTemp&
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  If LngMin = -1 Then LngMin = LBound(ArrayIn, 1)
  If LngMax = -1 Then LngMax = UBound(ArrayIn, 1)
  ' no sorting required
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  varMid = Empty
  varMid = ArrayIn((LngMin + LngMax) \ 2, lngColumn)
  Select Case True
  Case VBA.IsObject(varMid): i = LngMax: J = LngMin
  Case IsEmpty(varMid): i = LngMax: J = LngMin
  Case IsNull(varMid): i = LngMax: J = LngMin
  Case varMid = "": i = LngMax: J = LngMin
  Case VBA.VarType(varMid) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(varMid) > 17: i = LngMax: J = LngMin
  End Select
  If bDescending Then
    While i <= J
      While ArrayIn(i, lngColumn) > varMid And i < LngMax: i = i + 1: Wend
      While varMid > ArrayIn(J, lngColumn) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        For lngColTemp = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
          Tmp = ArrayIn(i, lngColTemp)
          ArrayIn(i, lngColTemp) = ArrayIn(J, lngColTemp)
          ArrayIn(J, lngColTemp) = Tmp
        Next lngColTemp
        i = i + 1: J = J - 1
      End If
    Wend
  Else
    While i <= J
      While ArrayIn(i, lngColumn) < varMid And i < LngMax: i = i + 1: Wend
      While varMid < ArrayIn(J, lngColumn) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        For lngColTemp = LBound(ArrayIn, 2) To UBound(ArrayIn, 2)
          Tmp = ArrayIn(i, lngColTemp)
          ArrayIn(i, lngColTemp) = ArrayIn(J, lngColTemp)
          ArrayIn(J, lngColTemp) = Tmp
        Next lngColTemp
        i = i + 1: J = J - 1
      End If
    Wend
  End If
  If (LngMin < J) Then Call ArrayQuickSortV(ArrayIn, lngColumn, bDescending, LngMin, J)
  If (i < LngMax) Then Call ArrayQuickSortV(ArrayIn, lngColumn, bDescending, i, LngMax)
End Sub
Sub ArrayQuickSortH(ByRef ArrayIn As Variant, _
                 Optional lngColumn& = 0, _
                 Optional bDescending As Boolean, _
                 Optional LngMin& = -1, _
                 Optional LngMax& = -1)
  On Error Resume Next
  Dim i&, J&
  Dim varMid As Variant, arrRowTemp As Variant
  Dim lngColTemp&
  If IsEmpty(ArrayIn) Then Exit Sub
  If VBA.InStr(TypeName(ArrayIn), "()") < 1 Then Exit Sub
  If LngMin = -1 Then LngMin = LBound(ArrayIn, 2)
  If LngMax = -1 Then LngMax = UBound(ArrayIn, 2)
  If LngMin >= LngMax Then Exit Sub
  i = LngMin: J = LngMax
  varMid = Empty
  varMid = ArrayIn(lngColumn, (LngMin + LngMax) \ 2)
  Select Case True
  Case VBA.IsObject(varMid): i = LngMax: J = LngMin
  Case IsEmpty(varMid): i = LngMax: J = LngMin
  Case IsNull(varMid): i = LngMax: J = LngMin
  Case varMid = "": i = LngMax: J = LngMin
  Case VBA.VarType(varMid) = vbError: i = LngMax: J = LngMin
  Case VBA.VarType(varMid) > 17: i = LngMax: J = LngMin
  End Select
  If bDescending Then
    While i <= J
      While ArrayIn(lngColumn, i) > varMid And i < LngMax: i = i + 1: Wend
      While varMid > ArrayIn(lngColumn, J) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        ReDim arrRowTemp(LBound(ArrayIn, 1) To UBound(ArrayIn, 1))
        For lngColTemp = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
          arrRowTemp(lngColTemp) = ArrayIn(lngColTemp, i)
          ArrayIn(lngColTemp, i) = ArrayIn(lngColTemp, J)
          ArrayIn(lngColTemp, J) = arrRowTemp(lngColTemp)
        Next lngColTemp
        Erase arrRowTemp
        i = i + 1: J = J - 1
      End If
    Wend
  Else
    While i <= J
      While ArrayIn(lngColumn, i) < varMid And i < LngMax: i = i + 1: Wend
      While varMid < ArrayIn(lngColumn, J) And J > LngMin: J = J - 1: Wend
      If i <= J Then
        ReDim arrRowTemp(LBound(ArrayIn, 1) To UBound(ArrayIn, 1))
        For lngColTemp = LBound(ArrayIn, 1) To UBound(ArrayIn, 1)
          arrRowTemp(lngColTemp) = ArrayIn(lngColTemp, i)
          ArrayIn(lngColTemp, i) = ArrayIn(lngColTemp, J)
          ArrayIn(lngColTemp, J) = arrRowTemp(lngColTemp)
        Next lngColTemp
        Erase arrRowTemp
        i = i + 1: J = J - 1
      End If
    Wend
  End If
  If (LngMin < J) Then Call ArrayQuickSortH(ArrayIn, lngColumn, bDescending, LngMin, J)
  If (i < LngMax) Then Call ArrayQuickSortH(ArrayIn, lngColumn, bDescending, i, LngMax)
End Sub
Code có sort theo nhiều cột và sort tiếng Việt được không bạn
 
Upvote 0

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Xếp được 2 cột nhưng tiếng Việt thì không được. VD chữ Đ bị xếp xuống dưới cùng.
Bài đã được tự động gộp:


File ví dụ ,,,,,,,,,,,,,,,
Code của bạn ngày càng hay /-*+/
Thêm tham số sort từ nhỏ tới lớn hoặc ngược lại sẽ khá đầy đủ tùy chọn
Cách so sánh trực tiếp rất khó viết code sort tiếng Việt, dùng sort của array list như cách bạn @befaint ổn hơn và dể viết code hơn
 
Upvote 0
Xếp được 2 cột nhưng tiếng Việt thì không được. VD chữ Đ bị xếp xuống dưới cùng.
Bài đã được tự động gộp:


File ví dụ
Xếp được 2 cột nhưng tiếng Việt thì không được. VD chữ Đ bị xếp xuống dưới cùng.
Bài đã được tự động gộp:


File ví dụ ,,,,,,,,,,,,,,,
Anh oi, cái này co

Xếp được 2 cột nhưng tiếng Việt thì không được. VD chữ Đ bị xếp xuống dưới cùng.
Bài đã được tự động gộp:


File ví dụ ,,,,,,,,,,,,,,,
Anh oi, cái này có sort dữ liệu được theo dòng không hở anh?
 
Upvote 0
Nghĩa là sao, tôi không hiểu? Bạn đã bao giờ dùng chức năng sort của Excel chưa, thứ này sort y như vậy?
Em cảm ơn anh ạ
Anh lấy ví dụ cho em sort theo hàng với anh nhé!
Và hàm có nhiều tham số quá, anh giải thiích từng tham số cho em và mọi người hiểu với.
 
Upvote 0
Em cảm ơn anh ạ
Anh lấy ví dụ cho em sort theo hàng với anh nhé!
Và hàm có nhiều tham số quá, anh giải thiích từng tham số cho em và mọi người hiểu với.
File ví dụ ở bài #9
Cú pháp ở bài #4

Bạn không chịu đọc, không chịu làm gì trơn!
 
Upvote 0
Code có sort theo nhiều cột và sort tiếng Việt được không bạn
Định nghĩa sort nhiều cột là như thế nào bác HieuCD?
Em chỉ biết sort nhiều tầng.
Cột sort các dữ liệu trùng thì sort cột thứ 2 nó là tầng sort thứ 2, cứ thế cho các tầng mong muốn.

Với thuật toán quick sort ở trên thì muốn sort bao nhiều tầng, không có gì khó.


Còn sort tiếng Việt, thêm các ràng buộc sử dụng Hàm StrComp là được.

Bác có thể tham khảo code tại bài viết:
 
Lần chỉnh sửa cuối:
Upvote 0
Khổ quá anh oi, thật sự đầu óc em ngu ơi là ngu
Nhưng mờ bài 4 và 9 em vẫn chưa hiểu được mà.
Trong file ví dụ đã có sub test hàm. Xem trong đó thì biết cú pháp, muốn chạy thì bấm là chạy.

Mà việc dùng hàm (chứ không phải thủ tục - Sub) để sắp xếp trong mảng là phục vụ mục đích chuyển tiếp khi code trước đó đã ra kết quả là 1 mảng nên cần sắp xếp để làm tiếp để đến kết quả cuối cùng.

Đa số công việc bình thường thì cứ dán mảng lên sheet rồi dùng lệnh của VBA Excel (ghi macro trình tự sort ra là có) để sắp xếp là hết chuyện.
 
Lần chỉnh sửa cuối:
Upvote 0
Cập nhật bài #1:
1. Thêm tùy chọn sắp xếp giảm/tăng dần: Cảm ơn gợi ý của @HieuCD cho tùy chọn này.
2. Đã sắp xếp được tiếng Việt; Cảm ơn @HeSanbi về gợi ý áp dụng hàm StrComp tại bài #15.

Hàm sắp xếp mảng này có 1 chỗ chưa ổn với các trường số có độ dài khác nhau ở các dòng. Ví dụ 1, 2, 10, 11, 20, 30 thì bị xếp thành 1, 10, 11, 2, 20, 30 (vì code xem đây là text và sắp theo kiểu text chứ không phải sắp theo number). Bạn nào biết chỉ cho tôi cách để hoàn thiện chỗ này chút.

Bài #1 không được phép sửa nên tôi đăng code ở đây:
Rich (BB code):
Function QuickSortArrayF(ByRef SortArray As Variant, Optional Order As Boolean = True, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0)
    On Error Resume Next

    'Sort a 2-Dimensional array

    ' SampleUsage: sort arrData by the contents of column 3
    '
    '   QuickSortArray arrData, , , 3

    '
    'Posted by Jim Rech 10/20/98 Excel.Programming

    'Modifications, Nigel Heffernan:

    '       ' Escape failed comparison with empty variant
    '       ' Defensive coding: check inputs

    Dim i As Long
    Dim j As Long
    Dim varMid As Variant
    Dim arrRowTemp As Variant
    Dim lngColTemp As Long

    If IsEmpty(SortArray) Then
        Exit Function
    End If
    If InStr(TypeName(SortArray), "()") < 1 Then  'IsArray() is somewhat broken: Look for brackets in the type name
        Exit Function
    End If
    If lngMin = -1 Then
        lngMin = LBound(SortArray, 1)
    End If
    If lngMax = -1 Then
        lngMax = UBound(SortArray, 1)
    End If
    If lngMin >= lngMax Then    ' no sorting required
        Exit Function
    End If

    i = lngMin
    j = lngMax
      
    varMid = Empty
    varMid = SortArray((lngMin + lngMax) \ 2, lngColumn)

    ' We  send 'Empty' and invalid data items to the end of the list:
    If IsObject(varMid) Then  ' note that we don't check isObject(SortArray(n)) - varMid *might* pick up a valid default member or property
        i = lngMax
        j = lngMin
    ElseIf IsEmpty(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf IsNull(varMid) Then
        i = lngMax
        j = lngMin
    ElseIf varMid = "" Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) = vbError Then
        i = lngMax
        j = lngMin
    ElseIf VarType(varMid) > 17 Then
        i = lngMax
        j = lngMin
    End If
    
'---------------------------
    If Order Then
        While i <= j
            While (StrComp(SortArray(i, lngColumn), varMid, 1) = -1 Or (SortArray(i, lngColumn) < varMid) And StrComp(SortArray(i, lngColumn), varMid, 1) = 0) And i < lngMax
                i = i + 1
            Wend
            While (StrComp(varMid, SortArray(j, lngColumn), 1) = -1 Or (varMid < SortArray(j, lngColumn)) And StrComp(varMid, SortArray(j, lngColumn), 1) = 0) And j > lngMin
                j = j - 1
            Wend
            If i <= j Then
                'Hoan doi cac dong
                ReDim arrRowTemp(LBound(SortArray, 2) To UBound(SortArray, 2))
                For lngColTemp = LBound(SortArray, 2) To UBound(SortArray, 2)
                    arrRowTemp(lngColTemp) = SortArray(i, lngColTemp)
                    SortArray(i, lngColTemp) = SortArray(j, lngColTemp)
                    SortArray(j, lngColTemp) = arrRowTemp(lngColTemp)
                Next
                Erase arrRowTemp
                i = i + 1
                j = j - 1
            End If
        Wend
    Else
        While i <= j
            While (StrComp(varMid, SortArray(i, lngColumn), 1) = -1 Or (SortArray(i, lngColumn) > varMid) And StrComp(varMid, SortArray(i, lngColumn), 1) = 0) And i < lngMax
                i = i + 1
            Wend
            While (StrComp(SortArray(j, lngColumn), varMid, 1) = -1 Or (varMid > SortArray(j, lngColumn)) And StrComp(SortArray(j, lngColumn), varMid, 1) = 0) And j > lngMin
                j = j - 1
            Wend
            'Hoan doi cac dong
            If i <= j Then
                ReDim arrRowTemp(LBound(SortArray, 2) To UBound(SortArray, 2))
                For lngColTemp = LBound(SortArray, 2) To UBound(SortArray, 2)
                    arrRowTemp(lngColTemp) = SortArray(i, lngColTemp)
                    SortArray(i, lngColTemp) = SortArray(j, lngColTemp)
                    SortArray(j, lngColTemp) = arrRowTemp(lngColTemp)
                Next
                Erase arrRowTemp
                i = i + 1
                j = j - 1
            End If
        Wend
    End If
'---------------------------
    If (lngMin < j) Then Call QuickSortArrayF(SortArray, Order, lngMin, j, lngColumn)
    If (i < lngMax) Then Call QuickSortArrayF(SortArray, Order, i, lngMax, lngColumn)
    
    QuickSortArrayF = SortArray
End Function

Function QuickSortArrayF2(ByRef SortArray As Variant, Optional Order As Boolean = True, Optional Order2 As Boolean = True, Optional lngMin As Long = -1, Optional lngMax As Long = -1, Optional lngColumn As Long = 0, Optional lngColumn2 As Long = 0)
Dim SortArr As Variant
Dim i As Long, j As Long, k As Long, D As Long, r As Long
    If lngColumn = 0 Then lngColumn = 1
    SortArray = QuickSortArrayF(SortArray, Order, , , lngColumn)
    ReDim TempArray(1 To UBound(SortArray, 1), 1 To UBound(SortArray, 2))
    For i = LBound(SortArray, 1) To UBound(SortArray, 1)
        k = k + 1
        On Error Resume Next
        If SortArray(i, lngColumn) <> SortArray(i + 1, lngColumn) Then
            If Err.Number = 9 Then
                On Error GoTo 0
                GoTo Sort
            End If
Sort:       If k > 1 Then
                ReDim SortArr(1 To k, 1 To UBound(SortArray, 2))
                For r = 1 To k
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArr(r, j) = SortArray(i - k + r, j)
                    Next
                Next
                SortArr = QuickSortArrayF(SortArr, Order2, , , lngColumn2)
                For D = i - k + 1 To i
                    For j = LBound(SortArray, 2) To UBound(SortArray, 2)
                        SortArray(D, j) = SortArr(D + k - i, j)
                    Next
                Next
                k = 0
            Else
                k = 0
            End If
        End If
    Next
    QuickSortArrayF2 = SortArray
End Function
 
Upvote 0
Hôm qua tính nói hàm của bạn bị đụng hàng "Siêu" rồi, không còn cửa. :p
Nhưng hôm nay, cái hàm kia nó tự động khiêm nhường, gỡ mất danh hiệu "sụp-pơ" rồi. Coi như hiệp đầu chưa có gì. :victory:
 
Upvote 0
Upvote 0
Thuật toán QuickSort là thuật toán rất tân tiến và hiệu quả. Tuy nhiên, nó sẽ có một vài trường hợp bị "hẫng". Để có thể tét QuickSort, phải tốn khá nhiều thời gian dựng dữ liệu và tìm chỗ "vùng mượt" (*1) cho hàm củea bạn. Hiện giờ tôi không đủ sức khoẻ để dựng tét tầm cỡ này.

Trong bài kia, theo đề bài thì bạn dùng ArrayList, đó là một công cụ của dot Net. Máy tôi đang dùng là Mac, không sử dụng được.

(*1) vùng mượt: sweet spot. Hầu hết các thuật toán đều có vùng mượt tức là vùng dữ liệu mà nó chạy mượt nhất. Chuyện này tôi đã đề cập nhiều lần khi đánh giá một phần mềm.
 
Upvote 0
Thấy bác cũng máu me vụ Sort nên em cũng góp vui code của em để bác tham khảo.
PHP:
Option Explicit

Private ListChar As String

Function QuickSortArray2D(iArray, Optional iRule = 1)
  Dim aResult, aIndex, aRule, x&, y&
  ReDim aIndex(LBound(iArray) To UBound(iArray))

  For x = LBound(iArray) To UBound(iArray)
    aIndex(x) = x
  Next x
  GetListChar ListChar
  If Not IsArray(iRule) Then aRule = Array(iRule) Else aRule = iRule
  x = LBound(aRule)
  QuickSortColumn aIndex, iArray, aRule(x), LBound(iArray), UBound(iArray)
  For x = x + 1 To UBound(aRule)
    QuickSortExtraColumn aIndex, iArray, aRule, x
  Next x
  ListChar = Empty

  ReDim aResult(LBound(iArray) To UBound(iArray), LBound(iArray, 2) To UBound(iArray, 2))
  For y = LBound(iArray, 2) To UBound(iArray, 2)
    For x = LBound(iArray) To UBound(iArray)
      aResult(x, y) = iArray(aIndex(x), y)
    Next x
  Next y
  QuickSortArray2D = aResult
End Function

Private Sub QuickSortColumn(iArrayIndex, iArray, iRule, iLo As Long, iHi As Long)
  Dim xBegin&, xEnd&, x&, y&, uCompare
  xBegin = iLo: xEnd = iHi
  x = Abs(iRule) + LBound(iArray, 2) - 1
  SelectCompare iArrayIndex, iArray, iRule, x, iLo, iHi - iLo + 1, uCompare

  While (xBegin <= xEnd)
    While (CompareValue(iArray(iArrayIndex(xBegin), x), uCompare, iRule) < 0 And xBegin < iHi)
      xBegin = xBegin + 1
    Wend
 
    While (CompareValue(iArray(iArrayIndex(xEnd), x), uCompare, iRule) > 0 And xEnd > iLo)
      xEnd = xEnd - 1
    Wend

    If (xBegin <= xEnd) Then
      SwapIndexArray iArrayIndex, xBegin, xEnd
      xBegin = xBegin + 1
      xEnd = xEnd - 1
    End If
  Wend

  If xBegin < iHi Then QuickSortColumn iArrayIndex, iArray, iRule, xBegin, iHi
  If iLo < xEnd Then QuickSortColumn iArrayIndex, iArray, iRule, iLo, xEnd
End Sub

Private Sub QuickSortExtraColumn(iArrayIndex, iArray, iRule, iRuleIndex)
  Dim x&, y&, z&, s1$, s2$:
  Dim xBegin&, xEnd&

  xBegin = LBound(iArrayIndex)
  x = xBegin
  While x < UBound(iArrayIndex)
    For y = LBound(iRule) To iRuleIndex - 1
      z = Abs(iRule(y)) + LBound(iArray, 2) - 1
      s1 = TypeName(iArray(iArrayIndex(x), z)) & CStr(iArray(iArrayIndex(x), z))
      s2 = TypeName(iArray(iArrayIndex(x + 1), z)) & CStr(iArray(iArrayIndex(x + 1), z))
    If s1 <> s2 Then
      xEnd = x
      If xBegin < xEnd Then QuickSortColumn iArrayIndex, iArray, iRule(iRuleIndex), xBegin, xEnd
      xBegin = x + 1
      Exit For
    End If
    Next y
    x = x + 1
  Wend
  xEnd = UBound(iArrayIndex)
  If xBegin < xEnd Then QuickSortColumn iArrayIndex, iArray, iRule(iRuleIndex), xBegin, xEnd
End Sub

Private Sub SelectCompare(iArrayIndex, iArray, iRule, iColumnIndex, iLo As Long, iSize As Long, iCompare)
  Dim u1, u2, u3
  u1 = Int(iSize * Rnd) + iLo: u1 = iArray(iArrayIndex(u1), iColumnIndex)
  u2 = Int(iSize * Rnd) + iLo: u2 = iArray(iArrayIndex(u2), iColumnIndex)
  u3 = Int(iSize * Rnd) + iLo: u3 = iArray(iArrayIndex(u3), iColumnIndex)
  If CompareValue(u1, u3, iRule) > 0 Then iCompare = u1: u1 = u3: u3 = iCompare
  iCompare = u2
  If CompareValue(u1, u2, iRule) > 0 Then
    iCompare = u1
  Else
    If CompareValue(u2, u3, iRule) > 0 Then iCompare = u3
  End If
End Sub

Private Sub SwapIndexArray(iArrayIndex, iIndex1 As Long, iIndex2 As Long)
  Dim xSwap&
  xSwap = iArrayIndex(iIndex1)
  iArrayIndex(iIndex1) = iArrayIndex(iIndex2)
  iArrayIndex(iIndex2) = xSwap
End Sub

Private Function CompareValue(ByVal iVal1, ByVal iVal2, ByVal iRule) As Integer
  Dim xType1 As Byte, xType2 As Byte
  xType1 = GetTypeValue(iVal1)
  xType2 = GetTypeValue(iVal2)
  If xType1 <> xType2 Then
    CompareValue = IIf(xType1 < xType2, -iRule, iRule)
  Else
    If xType1 <> 1 Then
      If iVal1 <> iVal2 Then
        Select Case xType1
          Case Is = 2, 3:
          Case Is = 5: CompareString iVal1, iVal2
          Case Is = 4, 6: iVal1 = CStr(iVal1): iVal2 = CStr(iVal2)
        End Select
        CompareValue = IIf(iVal1 < iVal2, -iRule, iRule)
      End If
    End If
  End If
End Function

Private Sub CompareString(iVal1, iVal2)
  Dim x&
  If InStr(1, iVal1, iVal2) = 1 Then Exit Sub
  If InStr(1, iVal2, iVal1) = 1 Then Exit Sub
  If StrComp(iVal1, iVal2, vbTextCompare) = 0 Then
    For x = 1 To Len(iVal1)
      If Mid(iVal1, x, 1) <> Mid(iVal2, x, 1) Then
        iVal1 = GetCharIndex(Mid(iVal1, x, 1))
        iVal2 = GetCharIndex(Mid(iVal2, x, 1))
        Exit Sub
      End If
    Next x
  Else
    For x = 1 To Application.Max(Len(iVal1), Len(iVal2))
      If StrComp(Mid(iVal1, x, 1), Mid(iVal2, x, 1), vbTextCompare) <> 0 Then
        iVal1 = GetCharIndex(Mid(iVal1, x, 1))
        iVal2 = GetCharIndex(Mid(iVal2, x, 1))
        Exit Sub
      End If
    Next
  End If
End Sub

Private Function GetTypeValue(iValue)
  Select Case TypeName(iValue)
    Case Is = "Empty", "Null": GetTypeValue = 1
    Case Is = "Double", "Long", "Single", "Currency", "Integer", "Byte": GetTypeValue = 2
    Case Is = "String": GetTypeValue = 5
    Case Is = "Date": GetTypeValue = 3
    Case Is = "Boolean": GetTypeValue = 4
    Case Is = "Error": GetTypeValue = 6
  End Select
End Function

Private Sub GetListChar(iListChar)
  Dim aTmp
  aTmp = Array(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, _
              97, 65, 224, 192, 225, 193, 7843, 7842, 227, 195, 7841, 7840, 259, 258, 7857, 7856, 7855, 7854, 7859, 7858, 7861, 7860, 7863, 7862, 226, 194, 7847, 7846, 7845, 7844, 7849, 7848, 7851, 7850, 7853, 7852, 98, 66, 99, 67, 100, 68, 273, 272, 101, 69, 232, 200, 233, 201, 7867, 7866, 7869, 7868, 7865, 7864, 234, 202, 7873, 7872, 7871, 7870, 7875, 7874, 7877, 7876, 7879, 7878, 102, 70, 103, 71, 104, 72, 105, 73, 236, 204, 237, 205, 7881, 7880, 297, 296, 7883, 7882, 106, 74, 107, 75, 108, 76, 109, _
              77, 110, 78, 111, 79, 242, 210, 243, 211, 7887, 7886, 245, 213, 7885, 7884, 244, 212, 7891, 7890, 7889, 7888, 7893, 7892, 7895, 7894, 7897, 7896, 417, 416, 7901, 7900, 7899, 7898, 7903, 7902, 7905, 7904, 7907, 7906, 112, 80, 113, 81, 114, 82, 115, 83, 116, 84, 117, 85, 249, 217, 250, 218, 7911, 7910, 361, 360, 7909, 7908, 432, 431, 7915, 7914, 7913, 7912, 7917, 7916, 7919, 7918, 7921, 7920, 118, 86, 119, 87, 120, 88, 121, 89, 7923, 7922, 253, 221, 7927, 7926, 7929, 7928, 7925, 7924, 122, 90, _
              91, 92, 93, 94, 95, 96, 123, 124, 125, 126)
  Dim x&
  For x = LBound(aTmp) To UBound(aTmp)
    iListChar = iListChar & ChrW(aTmp(x))
  Next x
End Sub

Private Function GetCharIndex(iChar) As Integer
  GetCharIndex = InStr(1, ListChar, iChar)
  If GetCharIndex = 0 Then
    GetCharIndex = AscW(iChar)
  Else
    GetCharIndex = GetCharIndex - 230
  End If
End Function

Hàm của em chỉ có 2 tham số:
- iArray: là mảng cần sắp xếp
- iRule: là cột cần sắp xếp, nếu là dấu trừ thì sắp xếp giảm dần, sắp xếp nhiều cột thì truyền mảng cột cần sắp xếp vào. Ví dụ iRule = [{1,-2,3}] là sắp xếp tăng dần theo cột 1, sau đó giảm dần theo cột 2 rồi tăng dần theo cột 3
 
Lần chỉnh sửa cuối:
Upvote 0
Thấy bác cũng máu me vụ Sort nên em cũng góp vui code của em để bác tham khảo.
PHP:
Option Explicit

Private ListChar As String

Function QuickSortArray2D(iArray, Optional iRule = 1)
  Dim aResult, aIndex, aRule, x&, y&
  ReDim aIndex(LBound(iArray) To UBound(iArray))

  For x = LBound(iArray) To UBound(iArray)
    aIndex(x) = x
  Next x
  GetListChar ListChar
  If Not IsArray(iRule) Then aRule = Array(iRule) Else aRule = iRule
  x = LBound(aRule)
  QuickSortColumn aIndex, iArray, aRule(x), LBound(iArray), UBound(iArray)
  For x = x + 1 To UBound(aRule)
    QuickSortExtraColumn aIndex, iArray, aRule, x
  Next x
  ListChar = Empty

  ReDim aResult(LBound(iArray) To UBound(iArray), LBound(iArray, 2) To UBound(iArray, 2))
  For y = LBound(iArray, 2) To UBound(iArray, 2)
    For x = LBound(iArray) To UBound(iArray)
      aResult(x, y) = iArray(aIndex(x), y)
    Next x
  Next y
  QuickSortArray2D = aResult
End Function

Private Sub QuickSortColumn(iArrayIndex, iArray, iRule, iLo As Long, iHi As Long)
  Dim xBegin&, xEnd&, x&, y&, uCompare
  xBegin = iLo: xEnd = iHi
  x = Abs(iRule) + LBound(iArray, 2) - 1
  SelectCompare iArrayIndex, iArray, iRule, x, iLo, iHi - iLo + 1, uCompare

  While (xBegin <= xEnd)
    While (CompareValue(iArray(iArrayIndex(xBegin), x), uCompare, iRule) < 0 And xBegin < iHi)
      xBegin = xBegin + 1
    Wend

    While (CompareValue(iArray(iArrayIndex(xEnd), x), uCompare, iRule) > 0 And xEnd > iLo)
      xEnd = xEnd - 1
    Wend

    If (xBegin <= xEnd) Then
      SwapIndexArray iArrayIndex, xBegin, xEnd
      xBegin = xBegin + 1
      xEnd = xEnd - 1
    End If
  Wend

  If xBegin < iHi Then QuickSortColumn iArrayIndex, iArray, iRule, xBegin, iHi
  If iLo < xEnd Then QuickSortColumn iArrayIndex, iArray, iRule, iLo, xEnd
End Sub

Private Sub QuickSortExtraColumn(iArrayIndex, iArray, iRule, iRuleIndex)
  Dim x&, y&, z&, s1$, s2$:
  Dim xBegin&, xEnd&

  xBegin = LBound(iArrayIndex)
  x = xBegin
  While x < UBound(iArrayIndex)
    For y = LBound(iRule) To iRuleIndex - 1
      z = Abs(iRule(y)) + LBound(iArray, 2) - 1
      s1 = TypeName(iArray(iArrayIndex(x), z)) & CStr(iArray(iArrayIndex(x), z))
      s2 = TypeName(iArray(iArrayIndex(x + 1), z)) & CStr(iArray(iArrayIndex(x + 1), z))
    If s1 <> s2 Then
      xEnd = x
      If xBegin < xEnd Then QuickSortColumn iArrayIndex, iArray, iRule(iRuleIndex), xBegin, xEnd
      xBegin = x + 1
      Exit For
    End If
    Next y
    x = x + 1
  Wend
  xEnd = UBound(iArrayIndex)
  If xBegin < xEnd Then QuickSortColumn iArrayIndex, iArray, iRule(iRuleIndex), xBegin, xEnd
End Sub

Private Sub SelectCompare(iArrayIndex, iArray, iRule, iColumnIndex, iLo As Long, iSize As Long, iCompare)
  Dim u1, u2, u3
  u1 = Int(iSize * Rnd) + iLo: u1 = iArray(iArrayIndex(u1), iColumnIndex)
  u2 = Int(iSize * Rnd) + iLo: u2 = iArray(iArrayIndex(u2), iColumnIndex)
  u3 = Int(iSize * Rnd) + iLo: u3 = iArray(iArrayIndex(u3), iColumnIndex)
  If CompareValue(u1, u3, iRule) > 0 Then iCompare = u1: u1 = u3: u3 = iCompare
  iCompare = u2
  If CompareValue(u1, u2, iRule) > 0 Then
    iCompare = u1
  Else
    If CompareValue(u2, u3, iRule) > 0 Then iCompare = u3
  End If
End Sub

Private Sub SwapIndexArray(iArrayIndex, iIndex1 As Long, iIndex2 As Long)
  Dim xSwap&
  xSwap = iArrayIndex(iIndex1)
  iArrayIndex(iIndex1) = iArrayIndex(iIndex2)
  iArrayIndex(iIndex2) = xSwap
End Sub

Private Function CompareValue(ByVal iVal1, ByVal iVal2, ByVal iRule) As Integer
  Dim xType1 As Byte, xType2 As Byte
  xType1 = GetTypeValue(iVal1)
  xType2 = GetTypeValue(iVal2)
  If xType1 <> xType2 Then
    CompareValue = IIf(xType1 < xType2, -iRule, iRule)
  Else
    If xType1 <> 1 Then
      If iVal1 <> iVal2 Then
        Select Case xType1
          Case Is = 2, 3:
          Case Is = 5: CompareString iVal1, iVal2
          Case Is = 4, 6: iVal1 = CStr(iVal1): iVal2 = CStr(iVal2)
        End Select
        CompareValue = IIf(iVal1 < iVal2, -iRule, iRule)
      End If
    End If
  End If
End Function

Private Sub CompareString(iVal1, iVal2)
  Dim x&
  If InStr(1, iVal1, iVal2) = 1 Then Exit Sub
  If InStr(1, iVal2, iVal1) = 1 Then Exit Sub
  If StrComp(iVal1, iVal2, vbTextCompare) = 0 Then
    For x = 1 To Len(iVal1)
      If Mid(iVal1, x, 1) <> Mid(iVal2, x, 1) Then
        iVal1 = GetCharIndex(Mid(iVal1, x, 1))
        iVal2 = GetCharIndex(Mid(iVal2, x, 1))
        Exit Sub
      End If
    Next x
  Else
    For x = 1 To Application.Max(Len(iVal1), Len(iVal2))
      If StrComp(Mid(iVal1, x, 1), Mid(iVal2, x, 1), vbTextCompare) <> 0 Then
        iVal1 = GetCharIndex(Mid(iVal1, x, 1))
        iVal2 = GetCharIndex(Mid(iVal2, x, 1))
        Exit Sub
      End If
    Next
  End If
End Sub

Private Function GetTypeValue(iValue)
  Select Case TypeName(iValue)
    Case Is = "Empty", "Null": GetTypeValue = 1
    Case Is = "Double", "Long", "Single", "Currency", "Integer", "Byte": GetTypeValue = 2
    Case Is = "String": GetTypeValue = 5
    Case Is = "Date": GetTypeValue = 3
    Case Is = "Boolean": GetTypeValue = 4
    Case Is = "Error": GetTypeValue = 6
  End Select
End Function

Private Sub GetListChar(iListChar)
  Dim aTmp
  aTmp = Array(32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, _
              97, 65, 224, 192, 225, 193, 7843, 7842, 227, 195, 7841, 7840, 259, 258, 7857, 7856, 7855, 7854, 7859, 7858, 7861, 7860, 7863, 7862, 226, 194, 7847, 7846, 7845, 7844, 7849, 7848, 7851, 7850, 7853, 7852, 98, 66, 99, 67, 100, 68, 273, 272, 101, 69, 232, 200, 233, 201, 7867, 7866, 7869, 7868, 7865, 7864, 234, 202, 7873, 7872, 7871, 7870, 7875, 7874, 7877, 7876, 7879, 7878, 102, 70, 103, 71, 104, 72, 105, 73, 236, 204, 237, 205, 7881, 7880, 297, 296, 7883, 7882, 106, 74, 107, 75, 108, 76, 109, _
              77, 110, 78, 111, 79, 242, 210, 243, 211, 7887, 7886, 245, 213, 7885, 7884, 244, 212, 7891, 7890, 7889, 7888, 7893, 7892, 7895, 7894, 7897, 7896, 417, 416, 7901, 7900, 7899, 7898, 7903, 7902, 7905, 7904, 7907, 7906, 112, 80, 113, 81, 114, 82, 115, 83, 116, 84, 117, 85, 249, 217, 250, 218, 7911, 7910, 361, 360, 7909, 7908, 432, 431, 7915, 7914, 7913, 7912, 7917, 7916, 7919, 7918, 7921, 7920, 118, 86, 119, 87, 120, 88, 121, 89, 7923, 7922, 253, 221, 7927, 7926, 7929, 7928, 7925, 7924, 122, 90, _
              91, 92, 93, 94, 95, 96, 123, 124, 125, 126)
  Dim x&
  For x = LBound(aTmp) To UBound(aTmp)
    iListChar = iListChar & ChrW(aTmp(x))
  Next x
End Sub

Private Function GetCharIndex(iChar) As Integer
  GetCharIndex = InStr(1, ListChar, iChar)
  If GetCharIndex = 0 Then
    GetCharIndex = AscW(iChar)
  Else
    GetCharIndex = GetCharIndex - 230
  End If
End Function

Hàm của em chỉ có 2 tham số:
- iArray: là mảng cần sắp xếp
- iRule: là cột cần sắp xếp, nếu là dấu trừ thì sắp xếp giảm dần, sắp xếp nhiều cột thì truyền mảng cột cần sắp xếp vào. Ví dụ iRule = [{1,-2,3}] là sắp xếp tăng dần theo cột 1, sau đó giảm dần theo cột 2 rồi tăng dần theo cột 3
Code chạy nhanh lắm. Nhưng rồi so ra thấy sao vẫn không giống với kết quả chức năng sort của Excel nhỉ?
 
Upvote 0
Code chạy nhanh lắm. Nhưng rồi so ra thấy sao vẫn không giống với kết quả chức năng sort của Excel nhỉ?
Chắc do em cài bảng sắp xếp tiếng Việt khác với Excel. Tuy có nhanh nhưng khi dữ liệu lớn cũng không sánh với Excel Sort được :p
 
Upvote 0
Thuật toán QuickSort là thuật toán rất tân tiến và hiệu quả. Tuy nhiên, nó sẽ có một vài trường hợp bị "hẫng". Để có thể tét QuickSort, phải tốn khá nhiều thời gian dựng dữ liệu và tìm chỗ "vùng mượt" (*1) cho hàm củea bạn. Hiện giờ tôi không đủ sức khoẻ để dựng tét tầm cỡ này.

Trong bài kia, theo đề bài thì bạn dùng ArrayList, đó là một công cụ của dot Net. Máy tôi đang dùng là Mac, không sử dụng được.

(*1) vùng mượt: sweet spot. Hầu hết các thuật toán đều có vùng mượt tức là vùng dữ liệu mà nó chạy mượt nhất. Chuyện này tôi đã đề cập nhiều lần khi đánh giá một phần mềm.

Cho mình hỏi là QuickSort dịch sang tiếng Việt thì là "siêu hàm", hay "siêu nhanh", hay "siêu mạnh" vậy bạn ?
 
Upvote 0
Cho mình hỏi là QuickSort dịch sang tiếng Việt thì là "siêu hàm", hay "siêu nhanh", hay "siêu mạnh" vậy bạn ?
Hình như tiếng Việt là sọt kít, nghĩa dịch ra chả liên quan gì đến siêu hàm cả.
Có chăng là có một cái hàm nó sử dụng sọt kít, với cả đống ốp-sần, và chắc là có kỹ thuật móc nối ê-bi-ai thế nào để sử dụng cache thay cho RAM (*1). Và vì thế nó nghiễm nhiên tự xưng là siêu.

Chú thích: bữa nào rảnh phải viết một cái xiêu hàm mới được. (xiêu ở đây là xiêu lòng, tức là ý nói hàm uyển chuyển chiều lòng người dùng. Chớ nghĩ là xiêu vẹo nhé)

(*1) hầu hết các code QuickSort hoạt động thẳng trên mảng khai báo ở bộ nhớ ụ (heap memory) cho nên việc phí năng lượng chép trị byVal và hết bộ nhớ ngăn xếp (quicksort dùng đệ quy nên liên quan ngăn xếp) không thành vấn đề ở đây. Tốc độ chỉ còn là làm thế nào để các phần code và data sử dụng nhiều nhất được nằm luôn trong cache, thay vì nằm trong RAM - tốc độ của cache nhanh hơn ram nhiều.
 
Upvote 0

Bài viết mới nhất

Back
Top Bottom