【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默频。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值