一、基本思想
将第i个记录的关键字Ki,与前面的r[1]~r[i-1]个记录元素比较,将关键字大于Ki的 记录向后移一个位置,知道遇见关键字小于 Ki 的记录,该位置既为r[i]插入的位置。
在这里要注意,比较时,i为要比较记录的下标,则从 i-1 开始比,即和她之前的比。
r[0]用作监视哨;
二、具体例子
比如 关键字为 33 12 24 48 33 68 利用直接插入排序进行排序的具体过程如下:
初始状态 r[0] r[1] r[2] r[3] r[4 ] r[5] r[6]
33 12 24 48 33 68
待插入记录
第一趟 12 12 33 24 48 33 68
有序序列 待插入
第二趟 24 12 24 33 48 33 68
第三趟 48 12 24 33 48 33 68 注意看这趟比较是否多余
第四趟 33 12 24 33 33 48 68
第五趟 68 12 24 33 33 48 68 注意这趟是否也多余
这里呢。r[0]作为监视哨的作用有两个 :
1. 防止数组越界
2.存备查记录
三、核心代码
先写一下没有优化的代码
void insertSort(RecordList L)
{
for(i = 2;i <= L.length;i++ )
{
L.r[0] = L.r[i];
for(j = i-1;L.r[j].key > L.r[0].key;i++) //大于才用移
{
L.r[j+1] = L.r[j];
}
L.r[j+1] = L.r[0]; //插入到正确位置
}
}
刚才在举例子的时候,发现第三趟、第五趟,其实可以不用进行该趟排序,为什么他们不需要排序,因为 r[i] > r[i-1] ,也就是说,它已经大于前面排好序的最大数,所以它不用跑这一趟,不许再和前面的比较。下面是优化的代码
void insertSort(RecordList L)
{
for(i = 2;i <= L.length;i++ )
{
if(L.r[i].key < L.r[i-1].key )
{
L.r[0] = L.r[i];
for(j = i-1;L.r[j].key > L.r[0].key;i++) //大于才用移
{
L.r[j+1] = L.r[j];
}
L.r[j+1] = L.r[0]; //插入到正确位置
}
}
}
其实上面就是多加了一个 if判断,看这一趟需不需要再比较。
插入排序是稳定的,因为它需要一个元素空间作为辅助空间r[0] 做交换,所以空间复杂度为 O(1)
它适用于顺序存储结构,即数组,也适用于链式存储结构,在链式存储结构上,它不需要移动位置,而是修改相应的指针。
完整java代码:
package analyse;
public class Test{
public static void main(String[] args) {
int a[] = {33,12,25,46,33,68,19,80};
Test t = new Test();
a = t.f(a);
t.print(a);
}
private void print(int[] a) {
for(int i = 0;i < a.length;i++){
System.out.print(" "+ a[i]);
}
}
private int[] f(int a[]) {
int temp,j;
for(int i = 1;i<a.length;i++){
temp = a[i];
for(j = i-1;j > -1 && temp < a[j];j--){
a[j + 1] = a[j];
}
a[j+1] = temp;
}
return a;
}
}