希尔排序
希尔(shell)排序是Donald Shell于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。
希尔排序对直接插入排序改进的着眼点:
-
若待排序序列中==元素基本有序==时,直接插入排序的效率可以大大提高
-
如果待排序序列中==元素数量较小==时,直接插入排序效率很高
希尔排序算法思路:
将整个待排序序列分割成若干个子序列,在子序列内部分别进行直接插入排序,等到整个序列==基本有序==时,再对全体成员进行直接插入排序!
待解决问题:
-
如何分割子序列,才能保证最终能得到基本有序?
-
子序列内部如何进行直接插入排序?
分割方案
- 将有n个元素的数组分成n/2个数字序列,第i个元素和第i+n/2,i+n/2*m…个元素为一组;
- 对一组数列进行简单插入排序;
- 然后,调整增量为n/4,从而得到新的几组数列,再次排序;
- 不断重复上述过程,直到增量为1,shell排序完全转化成简单插入排序,完成该趟排序,则数组排序成功。
希尔排序流程:
具体源码实现:
import java.util.Arrays;
public class Test07_ShellSort {
public static void main(String[] args) {
//准备一个int数组
int[] array = {5, 2, 6, 5, 9, 0, 3};
System.out.println("排序前: "+ Arrays.toString(array));
//shell排序
shellSort(array);
//输出排序结果
System.out.println("排序后: "+ Arrays.toString(array));
}
//由简单插入排序 改造得到 shell排序
public static void shellSort(int[] array) {
int len = array.length;
if(len <= 1)
return;
//设置初始增量
int gap = len / 2;
//由增量控制整体排序次数
while(gap > 0) {
//插入排序改造
for(int i = gap; i < len; i++) {
//记录要插入的值
int value = array[i];
//有序序列的最后一个元素下标
int j = i - gap;
for(; j >= 0; j -= gap) {
if(value < array[j]) {
array[j + gap] = array[j];
}else {
break;
}
}
array[j+gap] = value;
}
System.out.println(Arrays.toString(array));
gap = gap / 2;
}
}
}