【VB】預留排序法(百萬條數據只需30毫秒)

哈里在最近的編程生活中,突發奇想,開始着手文本的分析。

期間涉及到了數組的排序。於是想也沒想祭出了自己祖傳的“撲克牌排序法”,即插值排序。

不過當後期數組元素個數大於100萬的時候,祖傳方法明顯慢了下來,需要長達幾十分鐘的排序(VB.6.0與VB.net均如此,VB6.0更慢)。

在排序算法的優化中,想到了一種新型排序方法:預留排序法。(新算法100萬條數據僅需29毫秒,名字起的比較隨意)

預留排序法的步驟主要有三步:

1、找到需要排序數組的最小值與最大值。(如果語言不支持負數組,則利用一個偏移將負值偏移至0)

2、獲取需要排序數組的每種出現過的值的重複數量。

3、通過內存位置預測,將需要排序的數組的遍歷序放入排序索引數組完成排序。

(以下例子默認需要排序的最小值大於或等於1)

VB6.0實例如下:(百萬條數據3.6秒)

Public Function 預留法排序(數組() As Long, 排序() As Long)
    Dim 數量() As Long, i As Long, 數組最大值 As Long, 偏移() As Long
    ReDim 排序(UBound(數組))
    For i = 1 To UBound(數組)
        If 數組(i) > 數組最大值 Then
            數組最大值 = 數組(i)
        End If
    Next
    ReDim 數量(數組最大值), 偏移(數組最大值)
    For i = 1 To UBound(數組)
        數量(數組(i)) = 數量(數組(i)) + 1
    Next
    For i = 1 To UBound(數組)
        偏移(數組(i)) = 偏移(數組(i)) + 1
        排序(數組求和(數量, 數組(i)) + 偏移(數組(i))) = i
    Next
End Function
Private Function 數組求和(數組() As Long, 截止序 As Long) As Long
    Dim i As Long
    For i = LBound(數組) To 截止序 - 1
        數組求和 = 數組求和 + 數組(i)
    Next
End Function

不得不說VB.NET的運算速度比VB6.0快得多得多,所以VB.net的實例哈里也準備了一份:(百萬條數據29毫秒)

Public Sub 預留法排序(數組() As Long, 排序() As Long)
    Dim 數量() As Long, i As Long, 數組最大值 As Long, 偏移() As Long
    ReDim 排序(UBound(數組))
    '獲得數組最大值
    For i = 1 To UBound(數組)
        If 數組(i) > 數組最大值 Then
            數組最大值 = 數組(i)
        End If
    Next
    ReDim 數量(數組最大值), 偏移(數組最大值)
    '重複值劃分統計
    For i = 1 To UBound(數組)
        數量(數組(i)) += 1
    Next
    '最終排序
    For i = 1 To UBound(數組)
        偏移(數組(i)) += 1
        排序(數組求和(數量, 數組(i)) + 偏移(數組(i))) = i
    Next
End Function
Private Function 數組求和(數組() As Long, 截止序 As Long) As Long
    Dim i As Long, 輸出 As Long
    For i = LBound(數組) To 截止序 - 1
        輸出 += 數組(i)
    Next
    Return 輸出
End Function

(PS:以上所有耗時數據基於Intel i9 9900K默頻。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章