希尔排序介绍
希尔排序(Shell Sort)是插入排序的一种改进版本,也称为缩小增量排序。它的基本思想是将待排序的序列划分成若干个子序列,对每个子序列进行插入排序,通过逐步缩小增量的方式,使得整个序列变为有序序列
实现步骤
1.选择一个增量序列,通常选择希尔增量序列,即将待排序序列按照增量序列分成若干个子序列,每个子序列的元素个数相对较少,但是子序列之间的元素相对较多。
2.对每个子序列进行插入排序。插入排序的基本思想是将待排序元素插入到已经排好序的子序列中,不断重复这个过程,直到整个序列变为有序序列。
3.缩小增量序列,重复步骤2,直到增量序列为1。
4.对整个序列进行插入排序。
和插入排序比较的优势:
1.相对于插入排序,希尔排序的平均时间复杂度更低,稳定性更好。
2.希尔排序的空间复杂度通常比插入排序更低,尤其是对于大规模的数据集。
3.希尔排序可以处理部分满序的数据集,即子序列中有一部分元素已经有序,但是整个序列仍然存在较大的间隔。
代码演示希尔排序:
/**
* 希尔排序
* @param arr
*/
public static void shellSort(int[]arr){
if (null == arr || arr.length < 2){
return;
}
int[]step = {5,3,1};
for (int s = 0; s < step.length;s++){
for (int i = 0;i < arr.length;i++ ){
for (int j = i - step[s];j >= 0 && arr[j] > arr[j+step[s]] ;j -= step[s]){
swap(arr,j,j+step[s]);
}
}
}
}
和插入排序比较下,看下插入排序的代码
/**
* 插入排序
* @param arr
*/
public static void insertSort(int[]arr){
if (null == arr || arr.length < 2){
return;
}
for (int i = 1;i < arr.length;i++){
for (int j = i - 1; j >=0 && arr[j] > arr[j+1];j--){
swap(arr,j + 1,j);
}
}
}
对比下两者运行的速度。
1.先生成一个随机数组。
/**
* 生成随机数组,
* @param len 数组最大长度
* @param max 数组内的最大值
* @return
*/
private static int[] generateArray(int len,int max){
int len1 = (int)(Math.random()*(len + 1));
int[] arr = new int[len1];
for (int i = 0; i < arr.length;i++){
arr[i] = (int)(Math.random()*(max + 1)) + 1;
}
return arr;
}
2.复制数组
/**
* 拷贝数组
* @param arr
* @return
*/
public static int[] copyArr(int[]arr){
if (null == arr){
return null;
}
int[]copy = new int[arr.length];
for (int i = 0; i < arr.length;i++){
copy[i] = arr[i];
}
return copy;
}
3.写个main 方法测试下运行时间比较。
public static void main(String[] args) {
//先验证是不是成功。
// int times = 5000;
// int len = 200;
// int max = 10000;
// boolean flag = true;
// for (int i = 0; i < times;i++){
// int[] ints = generateArray(len, max);
// int[] copyArr = copyArr(ints);
// RadixSort(ints);
// mergeSort(copyArr);
// if (!isEqual(ints,copyArr)){
// flag = false;
// printArr(copyArr);
// }
// }
//
// System.out.println(flag ? "success" : "fail");
int len1 = 1000000;
int max1 = 100000;
int[] ints = generateArray(len1, max1);
int[] copyArr = copyArr(ints);
long l = System.currentTimeMillis();
shellSort(ints);
long l1 = System.currentTimeMillis();
System.out.println("希尔排序---数组长度:"+ints.length + " .耗时:"+(l1 - l));
long l2 = System.currentTimeMillis();
insertSort(copyArr);
long l3 = System.currentTimeMillis();
System.out.println("插入排序---数组长度:"+ints.length + " .耗时:"+(l3 - l2));
}
耗时结果: