[VBA] 演算法 - Counting Sort 計數排序法 找出 重複的值 重複的次數

  • 22637
  • 0

[VBA] 演算法 - Counting Sort 計數排序法 找出 重複的值 重複的次數

利用Counting Sort 計數排序法找出重複的值,及重複的次數,這演算法算蠻難的,但如果用心品嘗將受用無窮。

1

 
 
Option Explicit
Option Base 1 '訂義陣列起始數為1,不能為0,因為在excel儲存格沒有0的定義位置
Dim counts()
Dim RepCell() '重複數值
Dim RepNo() '重複數量
Dim RepCon As Long
Dim i As Long
Dim j As Long
Dim next_index As Variant
Dim min, max
Dim min_value As Variant, max_value As Variant
Sub mySort()
    Dim i As Long
    Dim StartT As Date
 
    Dim myArray(65535) As Long '定義陣列數量
    StartT = Timer
    For i = 1 To 65535
        myArray(i) = CLng(Rnd * 100000) '
    Next i
    '測試用陣列
    '=======================================
    '    Dim myArray()
    '    myArray = Array(5, 1, 1, 5, 3, 6, 1)
    '=======================================
    Cells.Clear
    Application.ScreenUpdating = False
    DoEvents
 
    Range("A1").Value = "隨機數字 " & Format(Timer - StartT, "00.00") & " sec."
    Range(Cells(2, 1), Cells(UBound(myArray) + 1, 1)) = Application.Transpose(myArray) '未排列
 
    StartT = Timer
    Call Countingsort(myArray)
    Range("B1").Value = "由小到大 " & Format(Timer - StartT, "00.00") & " sec."
    Range(Cells(2, 2), Cells(UBound(myArray) + 1, 2)) = Application.Transpose(myArray) '由小到大
 
    StartT = Timer
    Call Countingsort1(myArray)
    Range(Cells(2, 3), Cells(UBound(myArray) + 1, 3)) = Application.Transpose(myArray) '由大到小
    Range("C1").Value = "由大到小 " & Format(Timer - StartT, "00.00") & " sec."
End Sub
 
Sub Countingsort(list) '由小到大
    min_value = Minimum(list) '比出最小值
    max_value = Maximum(list) '比出最大值
 
    min = LBound(list) '陣列最小數量
    max = UBound(list) '陣列最大數量
 
    ReDim counts(min_value To max_value) '依最大值至最小值的範圍,定義該範圍數量的陣列
 
    ' Count the values.
    For i = min To max
        counts(list(i)) = counts(list(i)) + 1 '將list陣列值帶入counts陣列,並統計count陣列數量
    Next i
 
    ' Write the items back into the list array.
 
    ReDim RepCell(min To max, 1)
    ReDim RepNo(min To max, 1)
    next_index = min
    RepCon = min
    For i = min_value To max_value 'i迴圈表示,歷遍最小值至最大值的範圍數值
        Select Case counts(i) '判斷陣列存在與否
        Case Is = 1 '若等於1,表示陣列存在,且無重複
            For j = 1 To counts(i)
                list(next_index) = i '將數值遞回list陣列
                next_index = next_index + 1
            Next j
        Case Is > 1 '若大於1,表示陣列存在,且重複
            For j = 1 To counts(i)
                list(next_index) = i
                next_index = next_index + 1
            Next j
            RepCell(RepCon, 1) = i '帶入重覆數值
            RepNo(RepCon, 1) = counts(i) '帶入數值重覆次數
            RepCon = RepCon + 1
        End Select
 
    Next i
 
    Range(Cells(1, 4), Cells(1, 5)) = Array("重複數值", "重複次數")
    Range(Cells(2, 4), Cells(UBound(RepCell) + 1, 4)) = RepCell '填入重複數值
    Range(Cells(2, 5), Cells(UBound(RepNo) + 1, 5)) = RepNo '填入重複次數
End Sub
Sub Countingsort1(list) '由大到小
    min_value = Minimum(list) '比出最小值
    max_value = Maximum(list) '比出最大值
 
    min = LBound(list) '陣列最小數量
    max = UBound(list) '陣列最大數量
 
    ReDim counts(min_value To max_value) '依最大值至最小值的範圍,定義該範圍數量的陣列
 
    ' Count the values.
    For i = min To max
        counts(list(i)) = counts(list(i)) + 1 '將list陣列值帶入counts陣列,並統計count陣列數量
    Next i
 
    next_index = min
 
    For i = max_value To min_value Step -1 'i迴圈表示,歷遍最小值至最大值的範圍數值
        If counts(i) >= 1 Then '判斷陣列存在與否
            For j = 1 To counts(i) 'j迴圈表示,檢查存在的counts陣列數量
                list(next_index) = i '將數值遞回list陣列
                next_index = next_index + 1 'next_index表示陣列index
            Next j
        End If
    Next i
End Sub
 
Private Function Maximum(l)
    Dim s1, s2
    Dim i
    s1 = LBound(l) '取出陣列最小數量
    s2 = UBound(l) '取出陣列最大數量
    Maximum = l(s1) '定義初值
    For i = s1 To s2 '歷遍全部陣列
        If l(i) > Maximum Then Maximum = l(i) '若l(i)的值比初值(Maximum)大,初值(Maximum)則被l(i)取代
    Next i
End Function
 
Private Function Minimum(l)
    Dim s1, s2
    Dim i
    s1 = LBound(l)
    s2 = UBound(l)
    Minimum = l(s1)
    For i = s1 To s2
        If l(i) < Minimum Then Minimum = l(i)
    Next i
End Function
 範例下載:陣列-排序法.rar

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo