写在前面
- 上一篇更新了这个系列的排序算法(【十大排序算法系列】插入排序)。分析了插入排序的流程逻辑以及代码实现,下面来写下希尔排序
- 照例给出系列内所有算法的对比。。
- 常见的十大排序算法有:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序等。
常见的十大排序算法,时间复杂度和空间复杂度如下图:

希尔排序
介绍
- 希尔(Shell)排序又称为缩小增量排序,它是一种插入排序,算是直接插入排序算法的一种优化版。
- 由DL.Shell于1959年提出而得名
- 希尔排序的基本思想是,定义一个步长,然后根据步长把序列分成一个一个子组,然后对每个组使用直接排序算法进行排序,接着继续改变步长,重复上述逻辑,直到步长为 1 ,对整个序列进行直接排序,由于这时候序列基本有序了,所以此时插入排序算法的效率较高。
- 希尔排序的时间复杂度最差为O(n^2),最好情况时O(n),平均时间复杂度为O(n^1.3)。希尔排序空间复杂度O(1)。
逻辑
希尔排序算法是插入排序的一种优化,直接插入排序的话,如果序列没什么有序的规则,则这时候进行插入排序复杂度将会很高。那么希尔排序的一些做法是,先对序列进行一些预处理,即先把元素步长分组内的元素进行排序,对多个组进行排序以后,当最后步长为1,则序列全部元素为一个组,此时序列已基本有序,只需要进行少量的元素交换即可完成最终序列的排序。
动态图
希尔排序动态图

关于步长
步长的选择有争议,也有很多种说法,这里只采用 不断除以2 的方式。
初始步长 = 序列的长度 / 2
Java代码实现
import java.util.Arrays;
import java.util.Objects;
/**
* 希尔排序.
*
* @author linzp
* @version 1.0.0
* CreateDate 2021/1/7 9:04
*/
public class ShellSort {
public static void main(String[] args) {
int[] array = new int[]{1, 7, 4, 6, 3, 5};
Arrays.stream(array).forEach(System.out::print);
shellSort(array);
System.out.println();
Arrays.stream(array).forEach(System.out::print);
}
/**
* 希尔排序算法逻辑.
* 序列进行初步处理,使其大概有序.
* 即根据步长分组,对每组依次进行直接插入排序.
*
* @param array
*/
public static void shellSort(int[] array) {
if (Objects.isNull(array) || array.length <= 0) {
return;
}
//获取步长(希尔增量),初始一般为数组长度/2.
int gap = array.length;
//当步长大于1,不断进行除以2处理
while (gap > 1) {
gap = gap / 2;
//根据步长分组,对所有分组进行处理
for (int i = 0; i < gap; i++) {
//对当前分组内的元素进行直接插入排序处理
for (int j = i + gap; j < array.length; j = j + gap) {
int temp = array[j];
int k;
//直接插入排序判断,是否大于当前元素,不断往后腾位置
for (k = j - gap; k >= 0 && array[k] > temp; k = k - gap) {
array[k + gap] = array[k];
}
array[k + gap] = temp;
}
}
}
}
}
本文介绍了希尔排序算法,它是插入排序的优化版。希尔排序通过定义步长将序列分组排序,不断改变步长,直到步长为1时对整个序列排序。其时间复杂度最差为O(n^2),最好为O(n),平均为O(n^1.3),空间复杂度为O(1),还给出了Java代码实现。

1万+

被折叠的 条评论
为什么被折叠?



