基本思想
直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
时间复杂度
O(n^2)
空间复杂度
O(1)
稳定性
如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
代码
严格按定义书写的代码
1 void Insertsort1(int a[], int n) 2 { 3 int i, j, k; 4 for (i = 1; i < n; i++) 5 { 6 //为a[i]在前面的a[0...i-1]有序区间中找一个合适的位置 7 for (j = i - 1; j >= 0; j--) 8 if (a[j] <= a[i]) //注意插入排序是稳定的,所以a[j]=a[i]时也不处理 9 break; 10 11 //如找到了一个合适的位置 12 if (j != i - 1) 13 { 14 //将比a[i]大的数据向后移 15 int temp = a[i]; 16 for (k = i - 1; k > j; k--) 17 a[k + 1] = a[k]; 18 //将a[i]放到正确位置上 19 a[k + 1] = temp; 20 } 21 } 22 }
将上面代码进行简化,将搜索和数据后移这二个步骤合并。
1 void Insertsort2(int a[], int n) 2 { 3 int i, j; 4 for (i = 1; i < n; i++) 5 { 6 int temp = a[i]; 7 for (j = i - 1; j >= 0 && a[j] > temp; j--) 8 a[j + 1] = a[j]; 9 a[j + 1] = temp; 10 } 11 print(a, 10); 12 }
在某些极端的情况下,对内存需要特别严格时,比如不用temp变量(去掉哨兵)完成直接插入排序,又该如何实现呢。
1 inline void Swap(int &a, int &b) 2 { 3 if (a != b) 4 { 5 a ^= b; 6 b ^= a; 7 a ^= b; 8 } 9 } 10 void Insertsort3(int a[], int n) 11 { 12 int i, j; 13 for (i = 1; i < n; i++) 14 for (j = i - 1; j >= 0 && a[j] > a[j + 1]; j--) 15 Swap(a[j], a[j + 1]); 16 }