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

Liên hệ QC

Maika8008

Thành viên gạo cội
Tham gia
12/6/20
Bài viết
4,763
Được thích
5,719
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:
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
Web KT

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

Back
Top Bottom