持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
作者平台:
| CSDN:blog.csdn.net/qq_4115394…
| 知乎:www.zhihu.com/people/1024…
| GitHub:github.com/JiangXia-10…
| 微信公众号:1024笔记
本文一共2143字,预计阅读7分钟
前言
前文回顾:前面的文章排序算法系列:详解冒泡排序算法及其java实现和排序算法:详解选择排序算法及其java实现、排序算法:详解插入排序算法及其java实现分别介绍了排序算法中比较经典的冒泡排序、选择排序算法以及插入排序(直接插入排序),其中选择排序是非稳定排序算法,而直接插入排序和冒泡排序是稳定排序算法,插入排序分为两种:平时说的插入排序一般指的是直接插入排序,另一种插入排序是希尔排序算法,今天一起复习另外一种非稳定的插入排序算法:希尔排序算法!
什么是希尔排序
之所以说希尔排序也是属于插入排序,因为希尔排序是在前面说的直接插入排序的基础之上改进的一种插入排序算法,所以它的核心逻辑也是直接插入排序,希尔排序又叫做缩小增量排序。
希尔排序的核心逻辑就是根据一定的增量将数据进行分组,然后对每一组进行直接插入排序进行排序。
比如对于数组numbers={5,3,7,2,6,9,1,8,4,0},第一次排序需要先确定一个小于numbers长度的增量step作为第一个增量(对于增量的选取其实也会比较影响算法的时间复杂度,这里一般常用的选取规则为待排序数组长度的一半,即step=numbers.length/2),那么这里的增量step就是10/2=5,所以整个表的元素就根据增量被分成了5组,分别是(5,9),(3,1),(7,8),(2,4),(6,0)。然后分别对每组元素根据需要的升序降序规则进行直接插入排序,结果为(5,9),(1,3),(7,8),(2,4),(0,6)。
第二次排序的增量step=上次step/2,这里取2,则整个表被分为2组,分别为(5,9,1,3,7)和(8,2,4,0,6)。然后分别对每组元素进行直接插入排序,则第二次的排序后的结果为(1,3,5,7,9)、(0,2,4,6,8)。
第三次排序时,增量为1,即此时整个表为一组,对整个表进行直接插入排序,使得其有序,最终结果为(0,1,2,3,4,5,6,7,8,9)。
可以发现希尔排序对于直接插入排序的改进减少了直接插入排序的移动次数,因为直接插入排序最好的情况下是本身就是有序的,有序的情况下, 只需要比较,无须移动,所以时间复杂度更小。而且虽然一次分组的组内直接插入排序的是稳定的,但在后续多次的分组和不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,那么相等元素的相对位置还是可能会发生变化,最后其稳定性就会被打乱,所以希尔排序是非稳定排序。
希尔排序的java实现
通过上述分析,可以对希尔排序进行代码实现,注释和方法如下:
public class ShellSort {
public static void main(String[] args) {
int[] number = {5,3,7,2,6,9,1,8,4};
System.out.println("希尔排序之前:");
for (int i = 0; i <number.length ; i++) {
System.out.print(number[i]+" ");
}
shellSort(number);
System.out.println("\n希尔排序之后:");
for (int i = 0; i <number.length ; i++) {
System.out.print(number[i]+" ");
}
}
public static void shellSort(int[] numbers){
//设置初始步长,一般是数据长度/2
int step = numbers.length/2;
//临时变量
int temp = 0;
int count=0;
//只要步长大于0
while (step>0){
//这里对所有数据下标差为步长的元素组进行直接插入排序
for (int i = step; i < numbers.length; i++) {
temp=numbers[i];
count=i-step;
//对根据步长进行分组的元素组进行排序
while(count>=0&&temp<numbers[count]){
numbers[count+step]=numbers[count];
count-=step;
}
numbers[count+step]=temp;
}
//每次排序完之后步长都为上次步长的一半
step/=2;
}
}
}
结果如下:
总结
希尔排序的核心逻辑就是根据一定的增量对待排序数组进行分组,每次对分组的组内元素进行直接插入排序,直至增量为1,即最后对整个数组进行一次直接插入排序。