二十六讲 VBA排序方法之插入排序与希尔排序

插入排序

从数组的第二个元素往下循环,每一个数字都要和他上面的所有数字进行比较,如果遇到比他大的数字,那么比他大的数字就要下沉一个,比他小的数字不变,大数字下沉后就会留出来一个空间,那么当前数字就会插入到那个空间

Sub 插入排序()

Dim arr, temp, x, y, imax, k, k1, k2

arr = Range("a1:a10")

For x = 2 To UBound(arr)

temp = arr(x, 1)

For y = x - 1 To 1 Step -1

If arr(y, 1) <= temp Then Exit For '如果上面的数都没有它大,没必要再找,跳出for循环,直接到下一步

arr(y + 1, 1) = arr(y, 1)

k1 = k1 + 1

Next y

arr(y + 1, 1) = temp '接上一步跳出for循环的语句

k2 = k2 + 1

Next x

Range("b2").Resize(UBound(arr)) = arr

MsgBox k1

End Sub


希尔排序

是插入排序法的改进版,大大提高了插入排序法的效率。

原理:插入排序是挨着的,希尔排序是间隔的比较。插入排序下降一个位置,希尔排序下降一个间隔。需要设置很多间隔。

Sub 希尔排序()

Dim arr

Dim 总大小, 间隔, x, y, temp, t

t = Timer

arr = Range("a1:a30")

总大小 = UBound(arr) - LBound(arr) + 1

间隔 = 1   '间隔初始值为1

If 总大小 > 13 Then     '这里记住13,大于13计算间隔数,小于的话就用插入排序法,也就是间隔为1

Do While 间隔 < 总大小

间隔 = 间隔 * 3 + 1  '经验证这是最有效的间隔设置方法

Loop

间隔 = 间隔 \ 9  '反斜杠是四舍五入取整数的意思,比如9\4就是2

End If

Do While 间隔   '使用多个间隔来计算,使用do while 循环

For x = LBound(arr) + 间隔 To UBound(arr) '从这里开始就是插入排序法了

temp = arr(x, 1)

For y = x - 间隔 To LBound(arr) Step -间隔

If arr(y, 1) <= temp Then Exit For

arr(y + 间隔, 1) = arr(y, 1)

k1 = k1 + 1

Next y

arr(y + 间隔, 1) = temp

Next x

间隔 = 间隔 \ 3

Loop

MsgBox k1 'k是计数器,可以看到多少次

Range("b2").Resize(UBound(arr)) = arr

End Sub

总结:希尔排序是基于插入排序的以下两点性质而提出改进方法的:

插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率

但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位

算法思路:

先取一个正整数 d1(d1 < n),把全部记录分成 d1 个组,所有距离为 d1 的倍数的记录看成一组,然后在各组内进行插入排序

然后取 d2(d2 < d1)

重复上述分组和排序操作;直到取 di = 1(i >= 1) 位置,即所有记录成为一个组,最后对这个组进行插入排序。一般选 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。

上述信息摘自http://bubkoo.com/2014/01/15/sort-algorithm/shell-sort/


二十六讲 VBA排序方法之插入排序与希尔排序_第1张图片
二十六讲 VBA排序方法之插入排序与希尔排序_第2张图片


二十六讲 VBA排序方法之插入排序与希尔排序_第3张图片

关于希尔排序的间隔一点补充,涉及到步长的选择

内容摘自http://blog.csdn.net/u010383982/article/details/42302623


二十六讲 VBA排序方法之插入排序与希尔排序_第4张图片

你可能感兴趣的:(二十六讲 VBA排序方法之插入排序与希尔排序)