一、直接插入排序:
1.基本思想:
依次将每个记录插入到一个有序的子序列中去,插入后该记录序列仍是有序的。
2.具体做法:
先将待排序的记录序列中的第一个记录看成是一个有序子序列,然后从第二个记录起逐个进行插入,直至整个记录序列变成按关键字非递减有序的序列为止。
3.举例:
初始关键字: 8 3 2 5 9 4 6
i=1 : [ 8 ] 3 2 5 9 4 6
i=2 : [ 3 8 ] 2 5 9 4 6
i=3 : [ 2 3 8 ] 5 9 4 6
i=4 : [ 2 3 5 8 ] 9 4 6
i=5 : [ 2 3 5 8 9 ] 4 6
i=6 : [ 2 3 4 5 8 9 ] 6
排序结果: [ 2 3 4 5 6 8 9 ]
4.算法:
public void InsertSort(int a[], int n)
/* 用直接插入排序法对a[0]~a[n-1] 排序 */
{
int i, j;
int temp;
for (i = 1; i < n; i++) {
temp = a[i]; /* 将要插入的记录暂存到temp 中 */
j = i - 1; /* 从有序子序列的最高位开始比较 */
while (j >= 0 && temp < a[j]) {
a[j + 1] = a[j]; /* 将关键字>temp的记录后移 */
j--;
}
a[j + 1] = temp; /* 插入到正确位置 */
}
}
辅助空间:O(1)
时间:
(1)关键字的比较次数
最好(“ 正序” ): n-1
最坏(“ 逆序“): n(n-1) / 2
(2 )记录的移动次数
开始时,将要插入的记录→temp ,移动1,最后,将记录插入适当位置,即 temp →a[j+1] ,移动1次。比较后,若temp.key<a[j].key ,则 a[j] →a[j+1]
最小移动量(“正序”时):2(n-1)
最大移动量(“逆序”时):(n-1)(n+4)/ 2
∴ 直接插入排序的 时间复杂度 为O(n^2)。
二、折半插入排序
1.基本思想:
先将待排序的记录序列中的第一个记录看成是一个有序子序列,然后从第二个记录起依次将每个记录插入到一个有序的子序列中去,插入后该序列仍是有序的。但在查找插入位置时,不是采用顺序查找,而是采用折半查找。
2.算法:
public void BInsertSort(int a[], int n)
/* 用折半插入排序法对a[0]~a[n-1] 排序 */
{
int i, j, low, high, mid;
int temp;
for (i = 1; i < n; i++) {
temp = a[i]; /* 将要插入的记录暂存到temp 中 */
low = 0;
high = i - 1;
while (low <= high) /* 在有序子序列中折半查找插入位置 */
{
mid = (low + high) / 2;
if (temp < a[mid])
high = mid - 1;
else
low = mid + 1;
}
for (j = i - 1; j > high; j--)
a[j + 1] = a[j]; /* 将关键字>temp 的记录后移 */
a[high + 1] = temp; /* 插入 */
}
}
注:折半查找是先比较找到位置然后一起移动,因此比较次数并不比直接插入少。