希尔排序也成为“缩小增量排序”,其基本原理是,现将待排序的数组元素分红多个子序列,使得每一个子序列的元素个数相对较少,而后对各个子序列分别进行直接插入排序,待整个待排序列“基本有序”后,最后在对全部元素进行一次直接插入排序。所以,咱们要采用跳跃分割的策略:将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后获得的结果是基本有序而不是局部有序。希尔排序是对直接插入排序算法的优化和升级。
所谓的基本有序,就是小的关键字基本在前面,大的基本在后面,不大不小的基本在中间,例如{2,1,3,6,4,7,5,8,9,}就能够称为基本有序了。但像{1,5,9,3,7,8,2,4,6}这样,9在第三位,2在倒数第三位就谈不上基本有序。java
希尔排序的关键并非随便分组后各自排序,而是将相隔某个“增量”的记录组成一个子序列,实现跳跃式移动,使得排序的效率提升。须要注意的是,增量序列的最后一个增量值必须等于1才行。另外,因为记录是跳跃式的移动,希尔排序并非一种稳定的排序算法。
希尔排序最好时间复杂度和平均时间复杂度都是,最坏时间复杂度为
。//最好状况即不须要交换数据算法
以数组{26, 53, 67, 48, 57, 13, 48, 32, 60, 50 }为例,步长序列为{5,2,1}
初始化关键字: [26, 53, 67, 48, 57, 13, 48, 32, 60, 50 ]数组
最后的排序结果:
13 26 32 48 48 50 53 57 60 67优化
先从array[0]开始,以incrementNum为增量的进行直接插入排序,直到数组末尾,而后从array[1]开始重复:以incrementNum为增量的进行直接插入排序; 而后从array[1]开始重复......一直到array[n]。spa
而后取一个小于上一步增量的新的增量(好比设置为incrementNum/2),对前一个步骤的结果array进行遍历,直接插入排序....code
再取小于上一步增量的新的增量,重复进行:遍历,直接插入排序blog
直到新的增量小于1以后再退出循环排序
好比如今有数组{82 ,31 ,29 ,71, 72, 42, 64, 5,110} 第一次取增量设置为array.length/2 = 4 先从82开始以4为增量遍历直到末尾,获得(82,42) 排序获得{42 ,31 ,29 ,71, 72, 82, 64, 5,110}。 而后从第二个数31开始重复上一个步骤,获得(31,64) 排序获得{42 ,31 ,29 ,71, 72, 82, 64, 5,110}....... 以4为增量的遍历完数组以后,获得的结果是{42,31,5,71,72,82,64,29,110}图片
而后从新区增量,这儿设定为incrementNum/2 = 2,对{42 ,31,5,71,72,82,64,29,110}重复步骤1。 完事以后,在取新的增量,重复步骤1。 直到取到的增量小于1,退出循环。rem
好比有这么一种状况:对一个无序数组进行从小到大的排序,可是数组的最后一个位置的数是最小的,咱们要把它挪到第一个位置,其余位置的都要日后移动,要是这个数组很是大,那么直接插入排序的开销就很是大。
package sort; import java.util.Arrays; /** * 希尔排序 * * @author TangJiang 2017年11月24日 下午4:51:37 * */ public class ShellSort { public static void ShellSortTest(int[] arr) { if (arr == null || arr.length <= 1) { return; } // 设置初始增量 int increase = arr.length / 2; while (increase >= 1) { for (int i = 0; i < arr.length; i++) { // 进行跳跃插入排序 for (int j = i; j < arr.length - increase; j = j + increase) { // 比较大小交换数据 if (arr[j] > arr[j + increase]) { int temp = arr[j]; arr[j] = arr[j + increase]; arr[j + increase] = temp; } } } // 设置新的增量 increase = increase / 2; } } public static void main(String[] args) { int[] a = { -1, 3, 6, 2, 6, 89, 3 }; ShellSortTest(a); // for (int i : a) { // System.out.println(i + ""); // } System.out.println(Arrays.toString(a)); } }