一、算法思想
插入排序是一种对少量数据进行排序的有效算法,最好情况,待排序序列有序 时间复杂度为0(n),最坏情况,待排序序列为逆序 时间复杂度为0(n*n)
算法思想是:维护一个有序区域,把元素一个个插入有序区域的适当位置,直到所有元素都有序位置。
二、算法描述
给定无序数组如下:
5,8,6,3,9,2,1,7
第一轮
让元素8与有序区域的元素依次比较,也就是8与5比较,结果如下:
5,8,6,3,9,2,1,7
第二轮
让元素6,与有序区域的元素依次比较,也就是6与5,8比较,结果如下:
5,6,8,3,9,2,1,7
第三轮
让元素3,与有序区域的元素依次比较,也就是3与5,6,8比较,结果如下:
3,5,6,8,9,2,1,7
…
直到所有元素都排序完毕
三、算法实现
private int[] insertSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
//从第二个位置开始比较,类似冒泡排序一样
//冒泡排序:从所有范围开始排序,逐渐缩小排序范围
//插入排序:从1开始排序,逐渐扩大比较范围到所有
for (int j = i; j > 0; j--) {
if (nums[j - 1] > nums[j]) {
int temp = nums[j];
nums[j] = nums[j - 1];
nums[j - 1] = temp;
}
}
}
return nums;
}
四、插入排序的优化
取消两两交换,找到插入位置,插入位置后的元素后移一位,再将元素赋值给插入位置
private int[] insertSortV2(int[] nums) {
for (int i = 1; i < nums.length; i++) {
//从第二个位置开始比较,类似冒泡排序一样
//冒泡排序:从所有范围开始排序,逐渐缩小排序范围
//插入排序:从1开始排序,逐渐扩大比较范围到所有
//记录待排序元素,比较已排序区域,将大于元素后移一位,直到找到小于元素,然后插入待排序元素
//这种优化只能适用于在有序区域中插入元素,针对冒泡排序这种乱序区域的不能适用
int sortedNum = nums[i];
int index = i;
for (int j = i; j > 0; j--) {
if (nums[j - 1] > sortedNum) {
nums[j] = nums[j - 1];
index = j - 1;
continue;
}
break;
}
// 交换
nums[index] = sortedNum;
}
return nums;
}
五、希尔排序
插入排序在数组有序程度高时,排序效率高。为了提高数组的有序度,先进行分组插入排序,调整整体的有序度,最后再进行插入排序,这个就是希尔排序。
private int[] insertSortV3(int[] nums) {
// 按照d/2进行分割元素,每个d/2的元素组合在一起进行一组插入排序
// 循环d/2分组插入排序,直到d/2==1,这样通过多次的排序,将整体有序度提高,优化插入排序的运行环境
// 希尔排序的增量
int d= nums.length;
while(d>1){
// 希尔增量,每次折半
d=d/2;
//从第二个元素开始比较
for(int x=d;x<nums.length;x++){
int sortedNum = nums[x];
int index = x;
for (int j = x; j>= d; j=j-d) {
if (nums[j - d] > sortedNum) {
nums[j] = nums[j - d];
index = j - d;
continue;
}
break;
}
// 交换
nums[index] = sortedNum;
}
}
return nums;
}