直接插入排序

算法思想

每一趟将一个待排序关键字按照其值大小插入到已经排好序部分的适当位置上。
原始序列:49 38 65 97 76
第一次:49 | 38 65 97 76
第二次:38 49 | 65 97 76
第三次:38 49 65 | 97 76
第四次:38 49 65 97 | 76
第五次:38 49 65 76 97

  1. public void insertSort(int array[]){
  2. int temp, i ,j;
  3. for (i = 1; i < array.length; i++){
  4. //暂存待排序关键字
  5. temp = array[i];
  6. j = i - 1;
  7. //扫描已排序部分并移动
  8. while ((j >= 0) && (temp < array[j])){
  9. //若待排关键字小于当前比较值,则当前值后移一位
  10. array[j+1] = array[j];
  11. j--;
  12. }
  13. //待排关键字比较完毕,插入到合适位置
  14. //这里是j+1,因为跳出循环时j比起上次位置多执行了一次j--;
  15. array[j+1] = temp;
  16. }
  17. }

算法复杂度分析

时间复杂度

  1. 最坏情况,整个数组是逆序的,则temp < array[j]始终成立,对于每一次外循环,内循环都执行i次,i取值为1到n-1,则总次数为n(n-1)/2,即O(n2)。
  2. 最好情况,整个数组是顺序的,则temp < array[j]始终不成立,只执行外循环而不执行内循环,即O(n)。
  3. 综上,平均复杂度为O(n2)。

空间复杂度
算法所需的辅助空间不随待排序列规模的变化而变化,是个常量O(1)。

折半插入排序

算法思想

采用折半查找法查找插入位置。折半查找法的一个基本条件是序列已经有序。

  1. public void halfInsertSort(int array[]){
  2. int temp, low, mid, high, i, j;
  3. for (i = 1; i < array.length; i++){
  4. //暂存待排序关键字
  5. temp = array[i];
  6. //二分查找插入位置
  7. low = 0;
  8. high = i - 1;
  9. while (low <= high){
  10. mid = (low + high) / 2;
  11. //若待排序关键字小于中间位置值,则应寻找low-mid部分;
  12. //反之则寻找mid-high部分
  13. if (array[mid] > temp)
  14. high = mid - 1;
  15. else
  16. low = mid + 1;
  17. }
  18. //找到待插入位置后移动元素
  19. for (j = i-1; j >= high+1; j--){
  20. array[j+1] = array[j];
  21. }
  22. //移动结束后插入元素
  23. array[high+1] = temp;
  24. }
  25. }

算法复杂度分析

时间复杂度:折半插入适合关键字较多的场景,与直接插入排序相比 ,查找插入位置的时间大大减少,关键字移动次数和直接插入排序一样。折半插入排序的关键字比较次数和初始序列无关。最好情况是O(nlog2n),最差是O(n2),平均是O(n2)。
空间复杂度:O(1)。

希尔排序

算法思想

插入类排序 - 图1