之前自己依据选择和冒泡的代码,转换插入的代码时,得出了如下结果:
For i = 1 To n-1
For j = 2 To n
If a(j) > a(j - 1) Then
t = a(j)
a(j) = a(j - 1)
a(j - 1) = t
End If
Next j
Next i
后来被老师否定了,说“你的不是插入排序“!
当时就想一个问题“为什么自己写完了过程,抽象的代码却不是插入排序呢?”今天通过再次听老师讲插入排序,方才明白自己之所以抽象不出正确的代码,是因为:
第一,没有真正弄懂内外循环变量 j 与 i
第二,不清楚两者之间的联系。
故,现在想理一理“i”与“j”,以便帮助自己理解:
更正:不是”每一个“数,而是”某一个“数
所以两者的关系:外循环的i,即内循环的 j+1;内循环的j,即外循环的 i-1 。
清楚了这些,就能明确自己当时的代码是不正确的,而应该是:
For i = 2 To 10
If a(i) > a(i - 1) Then
'依次向前比较并互换,直到小于前面的数就不用比较了,停止循环
For j = i - 1 To 1 Step -1
If a(j + 1) < a(j) Then Exit For '已经小了,在有序区不用比较了,就停止
'互换
tmp = a(j + 1)
a(j + 1) = a(j)
a(j) = tmp
Next j
End If
Next i
今天才明白这种比较的方式叫“互换式”,直接插入法还有一种排序的方式叫“平移式“,与“互换式”的区别就在于,平移式中,会先将待插入数a(i)的值用一个临时变量temp保存起来,腾出空间,直到找到正确位置,将比较过的有序区的数依次向后平移,为a(i)腾出空间,放入a(i);而不用一个一个地互换,可能大家结合代码会更好理解:
For For i = 2 To 10
If a(i) > a(i - 1) Then '强调前面是一个有序区,
'不满足这个条件,a(i)已经小于前面的所有数
'意味着就直接扩大有序区,这也是效率的体现
temp = a(i) '用临时变量temp将a(i)里的值先保存起来,腾出空间
'依次向前比较并向后腾出空间,直到小于前面的数就不用比较了,停止循环
For j = i - 1 To 1 Step -1
If temp < a(j) Then Exit For '已经小了,在有序区不用比较了,就停止
a(j + 1) = a(j) '依次后移,腾出空间
'因为a(i)已经保存在temp中,第一个a(j+1)就是a(i)的恰当位置
Next j
a(j + 1) = temp '需要后移已经完成,腾出的位置,放a(i)
End If
Next i