本帖最后由 爱疯 于 2015-10-28 16:34 编辑
直接插入排序
就像整理扑克牌,桌上的牌是无序区,左手的是有序区,右手拿的那一张是待插入元素。1)有序区在前,无序区是在后。
2)每次,无序区第1个元素和有序区所有元素比较,再插入有序区的正确位置。
3)直至排序结束。
'**************************************************************************************
Sub test()
Dim arr()
arr = Array(8, 11, 4, 7)
' Call InsertionSort(arr)
' Call InsertionSort1(arr)
' Call InsertionSort2(arr)
Call InsertionSort3(arr)
MsgBox Join(arr, " ")
End Sub
'**************************************************************************************
'基本写法
Sub InsertionSort(arr)
Dim i&, j&, temp
For i = LBound(arr) + 1 To UBound(arr)
Debug.Print "前", "后", "第" & i & "次"
For j = i To LBound(arr) + 1 Step -1
Debug.Print j - 1, j
'升序:如果前>后,则交换
If arr(j - 1) > arr(j) Then temp = arr(j - 1): arr(j - 1) = arr(j): arr(j) = temp
Next
Next
End Sub
'**************************************************************************************
'改进:减少比较。
'因为有序区是有序的,只要前
Sub InsertionSort1(arr)
Dim i&, j&, temp
For i = LBound(arr) + 1 To UBound(arr)
Debug.Print "前", "后", "第" & i & "次"
For j = i To LBound(arr) + 1 Step -1
Debug.Print j - 1, j
'升序:如果前>后,则交换
If arr(j - 1) > arr(j) Then temp = arr(j - 1): arr(j - 1) = arr(j): arr(j) = temp Else Exit For
Next
Next
End Sub
'**************************************************************************************
'换一种写法
'与InsertionSort1等效,互换的3次赋值写在三处。
Sub InsertionSort2(arr)
Dim i&, j&, temp
For i = LBound(arr) + 1 To UBound(arr)
Debug.Print "后", "前", "第" & i & "次"
temp = arr(i) 't是哨兵,且是arr(i)的副本
For j = i To LBound(arr) + 1 Step -1
Debug.Print j, j - 1
'如果前
If arr(j - 1) < temp Then Exit For
arr(j) = arr(j - 1) '把前面值赋给后面,相当于记录后移
Next
arr(j) = temp 'arr(i)插入到正确的位置上
Next
End Sub
'**************************************************************************************
'二分查找插入排序
'对于插入位置,不再采取遍历有序区的方式,而是用二分查找。
Sub InsertionSort3(arr)
Dim i&, j&, temp, index&
For i = LBound(arr) + 1 To UBound(arr)
'通过二分查找,从有序区找出插入的位置index
index = binarySearch(arr, i - 1, arr(i))
If i <> index Then
temp = arr(i)
'后移元素,腾出arr(index)位置
For j = i - 1 To index Step -1
arr(j + 1) = arr(j)
Next j
arr(index) = temp
End If
Next
End Sub
'二分查找法
Function binarySearch(arr, max, x) As Long
Dim min, mid%
min = LBound(arr)
Do While min <= max
mid = (min + max) / 2
If x = arr(mid) Then binarySearch = mid: Exit Do
If x > arr(mid) Then min = mid + 1 Else max = mid - 1
Loop
binarySearch = min
End Function
'**************************************************************************************
插入排序_百度百科
http://baike.baidu.com/view/396887.htm
VBA编程技巧 之 排序算法初探
http://club.excelhome.net/thread-1004590-1-1.html 4楼
直接插入排序的基本思想和算法
http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.2.1.1.htm