**Shell排序的执行时间依赖于增量序列。
好的增量序列的共同特征:
① 最后一个增量必须为1;
② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
希尔排序的时间性能优于直接插入排序的原因:
①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
②当n值较小时,n和n^2的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(n^2)差别不大。
③在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
因此,希尔排序在效率上较直接插入排序有较大的改进。
折叠稳定性
希尔排序是不稳定的。参见上述实例,该例中两个相同关键字49在排序前后的相对次序发生了变化。
**
我们先来了解一下直接插入排序:
public static void insertSort(int[] array){
int tmp=0;
int i=1;
int j=0;
for(i=1;i<array.length;i++){
tmp=array[i];
for(j=i;j>=0;j--){
if(array[j]>tmp){
array[j+1]=array[j];
}else{
break;
}
}
array[j+1] = tmp;
}
}
输入:
输出:
视图分析:
Shell排序举例:
先给一个含15个元素的数组:
int[] array={12,5,9,34,6,8,33,56,89,0,7,4,22,55,77};
1、按以下方式将它分为五组,每组三个元素:
2、每组内进行直接插入排序如下:
3、将排序好的序列分为三组,每组五个元素:
4、同上,组内进行直接插入排序如下:
5、最后整个序列为一组并进行直接插入排序:
代码:
package YuanChuang;
import java.util.Arrays;
/*
* 直接插入排序:越有序越好排
* Shell(希尔)排序:采用分组的策略,让组内有序,
*
* */
public class ZhiJie {
public static void insertSort(int[] array){
int tmp=0;
int i=1;//计数
int j=0;//计数
for(i=1;i<array.length;i++){//对序列进行遍历,从第一个元素开始
tmp=array[i];//把array[i]放入tmp中
for(j=i;j>=0;j--){
if(array[j]>tmp){
array[j+1]=array[j];
}else{
break;
}
}
array[j+1] = tmp;
}
}
//相当于直接插入排序
public static void shell(int[] array,int gap){//gap分组
int tmp = 0;
int j = 0;//计数
for(int i = gap;i < array.length;i++){
tmp = array[i];
for(j = i-gap;j >= 0;j -= gap){
if(array[j]>tmp){
array[j+gap]=array[j];
}else{
break;
}
}
array[j+gap] = tmp;
}
}
public static void shellSort(int[] array){
int[] d = {5,3,1};//5、3、1相当于给shell中传进的 gap
for(int i = 0;i < d.length;i++){
shell(array,d[i]);//调用shell方法
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] array={12,5,9,34,6,8,33,56,89,0,7,4,22,55,77};
shellSort(array);
System.out.println(Arrays.toString(array));
}
}
输出结果为:
可见,与我们们用图推出来的结果相同。完美~~