希尔排序-Java实现
希尔排序 | What
希尔排序是插入排序的进阶版本.
我们知道,当一个数组是完全倒叙的,如9,8,7,6,5,4,3,2,1时,插入排序的复杂度最高,每次插入时,都要依次与前面的所有元素比较.因此插入排序适用于数据量小,并且有一定顺序的序列.
那么,希尔排序是怎么对插入排序的进阶呢? 实际上,希尔排序比插入排序多一步,这一步就是让后续的插入排序是在数据量小并且是在一定顺序的序列中执行.
那么,这一步是什么呢?这一步就是讲数组按照一定的步长(增量)来讲原始数组分组,在子数组中进行插入排序,并且在前面步长的基础上,依次减少步长来进行排序的.
希尔排序 | How
1. 首先将大的数组拆分成多个小的数组, 拆分时,按照一定步长(此处为5)分组.
2. 将各个小数组进行插入排序
3. 此时, 数组已经是有一定的顺序的数组了. 再次进行插入排序时, 速度会比第一次要快.
将步长设为3,再次执行分组.
4. 此时, 数组更加有序了. 再将步长设为2, 再次分组,并且每组插入排序
5. 将步长设置为1, 最终再对数列插入排序
希尔排序 | Why
希尔排序是对插入排序的优化
希尔排序解决的是插入排序对数据量大,并且完全无序或者大部分无序的数组时,效率低的问题.
希尔排序先将大数组分组进行拆入排序,解决插入排序处理数据量大时的低效问题
希尔排序每次减少步长依次执行的过程,利用前面的排序,使得整个数组变得基本有序.解决了插入排序处理大部分无序的低效问题.
希尔排序 | Java实现
public class ShellSort { public static void sort(Comparable[] c) { // 定义初始步长 int count = 0; for (int step = c.length / 2 + 1; step > 0; step = step / 2 ){ for (int i = step; i < c.length; i ++) { // 从c[i]元素开始, 插入到c[i-step], c[i-2step]的序列中, 使用插入排序 for (int j = i; j >= step; j-=step) { Comparable pre = c[j - step]; Comparable next = c[j]; if(pre.compareTo(next) > 0) { Comparable tmp = pre; c[j-step] = next; c[j] = tmp; } else { // 同一组内的元素,前面的顺序已经排好, 当遇到比改元素小的元素时,改组插入排序完毕 break; } System.out.println(String.format("第%s次排序, 结果: %s", ++count, Arrays.toString(c))); } } } } public static void main(String[] args) { Integer[] test = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; sort(test); } } |
输入: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
输出:
第1次排序, 结果: [4, 9, 8, 7, 6, 5, 10, 3, 2, 1]
第2次排序, 结果: [4, 3, 8, 7, 6, 5, 10, 9, 2, 1]
第3次排序, 结果: [4, 3, 2, 7, 6, 5, 10, 9, 8, 1]
第4次排序, 结果: [4, 3, 2, 1, 6, 5, 10, 9, 8, 7]
第5次排序, 结果: [1, 3, 2, 4, 6, 5, 10, 9, 8, 7]
第6次排序, 结果: [1, 3, 2, 4, 6, 5, 7, 9, 8, 10]
第7次排序, 结果: [1, 2, 3, 4, 6, 5, 7, 9, 8, 10]
第8次排序, 结果: [1, 2, 3, 4, 5, 6, 7, 9, 8, 10]
第9次排序, 结果: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]