希尔排序
学希尔排序的话 应该是学完插入排序了吧 ,如果没有学习的话我也有写 点击传送 ,可以先看看插入排序。因为希尔排序是把插入排序做了一个优化升级。
应用场景
我们使用插入排序去对一组数据进行排序的话最不希望看到的状况是哪种呢,很显然是数据的量大 而且大小数据极其不规律的情况 比如说小的数据都在后面 大的数据都在前面,因为插入排序的一个机制是拿当前的数据跟前面的数据不停的作比较然后插入,直至当前数据比前面的数据大。基于这样的机制我们遍历到越后面要进行的操作就越多,不停的比较和插入,效率和速度上就会很慢。
描述
希尔排序就很好的解决了插入排序在遇到数据多且极其不规律情况下的效率问题,大家首先想想我们如果要去解决插入排序遇到的这个数据多且不规律的问题 ,首先想到的办法是什么 ,当然是把大的数据放到前面 小的数据放到后面去,完毕后再用插入排序把这组相对有序的数据进行排序 就很好解决了不规律而导致的效率问题
可以先看一遍解决方法,看完图片和代码后再回来看一遍会好理解一些
解决方法
说明:增量(gap)一般取数组长度的一半 每次处理完一组数据后,(gap/2)得到下一次需要的增量值。
在希尔排序里我们首先会设置一个增量值 ,然后把数据按照增量分为几组(分组只是逻辑上的分组并非真的分组) 然后对分组内的数据进行排序。排序完成后 增量变小,然后再根据增量进行排序。依次类推 当增量为1时,再进行排序的时候,此时的数据经过前几次的处理,变得相对很规律。
图片(来自参考资料)
按照增量分组
让每组的数据有序
这里相当于是第二次排序了,修改了增量以后根据增量继续上面的操作
这时候把增量变为1 ,进行排序本质上就是进行一次插入排序。
代码实现
public static void main(String[] args) {
int[] arr = {1,7,2,3,5,4,6,0};
shellSort2(arr);
}
public static void shellSort2(int[] arr){
// 增量gap 并逐步的缩小增量
for (int gap = arr.length/2 ; gap > 0 ;
gap /= 2){
// 从第gap个元素 逐步对其所在组进行
//直接插入如排序
for (int i = gap ; i < arr.length ; i++){
int j = i;
int temp = arr[j];
if (arr[j] < arr[j - gap]){
while (j - gap >= 0 &&
temp < arr[j - gap]){
arr[j] = arr[j-gap];
j -= gap;
}
// 当退出while后 就给temp
//找到插入的位置
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
复杂度
时间复杂度:O(n log n)
空间复杂度 :O(1)
总结
可以看到希尔排序就是在插入排序的基础上加入了一个增(gap)值,然后根据增量值进行分组排序,增量值的作用就是在最后一次排序前把数据变得比较有序,提升代码效率。
参考资料
参考资料传送地址
https://blog.csdn.net/qq_39207948/article/details/80006224