希尔排序是1959年某个叫希尔的数学大大发明的,它其实就是在插入排序的基础上做了一些优化,但是效率却不知道提高了多少倍,我估计几万倍应该有吧(纯属个人瞎蒙)。插入排序是一个一个来插,而希尔排序则是有一个间隔,比如在容量为10的数组里将索引为1和3和5,7插入排序, 2和5,8插入排序。在这其中有一个增量的概念,可别以为这个增量是随便取的,如果取的不科学,可是效率也会大大的下降哦。最科学的取法就是 n = (n * 3)+1。 n是增量,初始值为1,按照这个公式一直增加到array.length / 3这个位置左右,然后在运算一次这个公式,就是最大的增量了。
package sort;
public class ShellSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 1000000;
int[] arr = new int[n];
for (int i = n; i > 0; i--) {
arr[i - 1] = i;
}
shellSort(arr);
/*for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}*/
}
/**我自己写的,效率要低一点。
* @param arr
*/
public static void shellSort(int[] arr){
int len = arr.length;
int h = 1;
while(h <= len/3){
h = (h * 3) +1;
}
while(h > 0){
for (int i = 0; i < len; i++) {
while(i + h < len && arr[i] > arr[i+h]){
int temp = arr[i];
arr[i] = arr[i+h];
arr[i+h] = temp;
}
}
h = (h - 1)/3;
}
}
/**书上例子,效率较高。
* @param arr
*/
public static void shellSort3(int[] arr){
int i,j,n=1,temp,len = arr.length;
//获取最大增量值
while(n<=len/3)
n = n*3+1;
//增量等于1时是最后一次排序
while(n > 0){
for (i = n; i < len; i++) {
temp = arr[i];
j = i;
//按照增量插入排序,由后往前排,这样效率高,我写的由前往后排,做了一些无用功。
while(j >= n && arr[j - n] >= temp){
arr[j] = arr[j - n];
j-=n;
}
arr[j] = temp;
}
//增量递减公式
n = (n - 1)/3;
}
}
}
在我机器上逆序排100w数据耗时44毫秒,快吧,比归并排序快多了,而且不需要额外空间。算法复杂度和代码量也比较优,快速排序复杂了一点(我是说如果写的更可能完美的情况下)代码量也多。虽然比快速排序稍慢一点点,但是综合其他,我感觉是排序的首选。专家也推荐一般情况下用希尔排序,如果你要更快一点点的话,才考虑快速排序。