希尔排序是在直接插入排序的基础上来的,理解了直接插入排序,希尔排序则非常简单:
public class ShellSort { public static void main(String[] args) { int a[] = {9,8,7,6,5,4,3,2,1,0}; sortByShell(a,a.length); System.out.println(Arrays.toString(a)); } public static void sortByShell(int a[],int high) { for (int i = 1; i < a.length; i++) { //每次开始的地方为 i,i的范围从 1 取到 末尾 int temp = a[i]; //要插入的元素 int j; for (j = i; j >= 1 && a[j - 1] > temp; j = j-1) { //连续的往前探寻(每次-1),找到一个比temp小的元素,插到这个元素后面 a[j] = a[j - 1]; //若当前元素比temp大则往后稍稍,只往后稍1个位置 } a[j] = temp; //将元素放到对应的位置 } } }
希尔排序,在最外面增加一层循环,使用上增量序列:
public class ShellSort { public static void main(String[] args) { int a[] = {9,8,7,6,5,4,3,2,1,0}; sortByShell(a,a.length); System.out.println(Arrays.toString(a)); } public static void sortByShell(int a[],int high) { for (int D = high >> 1; D > 0; D = D >> 1) { //希尔排序,在最外面增加一层循环,使用上增量序列 for (int i = D; i < a.length; i++) { //每次开始的地方,由D决定 int temp = a[i]; //要插入的元素 int j; for (j = i; j >= D && a[j - D] > temp; j = j-D) { //跳跃的往前探寻(每次-D),找到一个比temp小的元素,插到这个元素后面 a[j] = a[j - D]; //当前元素比temp大则往后稍稍,且往后稍D个位置 } a[j] = temp; //将元素放到对应的位置 } } } }
可以看出,希尔排序相比于直接插入排序它不是连续的往前探寻合适位置的,而是每次往前探寻D个位置,探寻不成功元素也是往后挪D个单位。D的计算直接影响希尔排序的复杂度,一般D1 = length/2,D2 = D1/2。还有很多增量的计算方法,比较复杂。
希尔排序的复杂度计算也是尚未完成的工作,O(n)最好情况,O(n^2)最坏情况,目前估计平均为 O(n^1.3),空间复杂度O(1)。希尔排序需要知道序列的步长,且在数据量不大时好用,数据量一大还不如快排的性能好(n很大时,n^1.3 > nlogn)