希尔排序的原理:将待排序数据元素集合按照一定的大小分块在块间的数据按照增量(步长)进行直接插入排序,然后根据一定的规则减少步长,再进行一次直接插入排序,直到步长小于1 。
希尔排序需要注意的是最后的增量一定是1 。
下面先给出Java实现代码:
public static void shellSort(int array[]) { if (null == array || 1 >= array.length) return; int step = 0, n = array.length, temp, j; int len = n; do { step = (int) Math.sqrt(n); for (int i = step; i < len; i++) { temp = array[i]; j = i - step; while (j >= 0 && temp < array[j]) { array[j + step] = array[j]; j -= step; } array[j + step] = temp; } n = step; } while (step > 1); }代码中初始步长为 Math.sqrt(n), n 为带排数据的长度,内部循环:
for (int i = step; i < len; i++) { temp = array[i]; j = i - step; while (j >= 0 && temp < array[j]) { array[j + step] = array[j]; j -= step; } array[j + step] = temp; }是对一个特定的步长做一次直接插入排序,当step == 1 时,该待排序集合基本有序所以不用大量移动元素。
按照上面步骤对下列元素集合做希尔排序的过程如下:
集合R = {37, 40, 38, 42, 461, 5, 7, 9, 12}
第一趟排序取步长 step = 3 ,
途中使用了三种不同的标记,表示了步长中的每一个元素{Ri , Ri+1 , ... Ri+step -1} 。
第二趟排序取步长step = Math.sqrt(3) = 1 ;
得到最后排好序的序列: 5 , 7, 9,12, 37, 38,42,61 。
在上面的例子中比较特殊,之进行了两趟排序就完成了,而且每趟排序中元素个数都是相同的。而在实际使用中一般step取值为:
step = step/2.2 ;
希尔排序的时间复杂度:O(N^3/2) 到 O(N^7/6) .