上一篇文章介绍了堆排序,这篇文章介绍下shell排序算法。
2.7、Shell排序算法
在介绍shell排序算法之前,我们先回顾下直接插入排序算法的流程:
1、首先对数组的前两个数据进行从小到大的排序。
2、接着将第3个数据与排好序的两个数据比较,将第3个数据插入合适的位置。
3、然后将第4个数据插入已排好序的前3个数据中
4、不断重复上述过程,直到把最后一个数据插入合适的位置。最后便完成了对原始数组从小到大的排序。
由插入排序算法的流程我们可以知道:每次向已排好序的数据中插入一个新的数据时,新插入的数据都要跟已排好序的数据一一比较,直到找到自己的位置。如果数据量比较大,数据比较的次数较多影响效率。shell排序算法也用到了上面的直接插入排序算法,但是每一次使用直接插入排序算法时,数组中的数据已经是基本有序的了,这就大大提高了排序的效率。
实现思路:
1、将有n个元素的数组分成n/2个数字序列,第1个数据和第n/2+1个数据为一对,后面的一次类推(即分组)。
2、一次循环使每一个序列对排好顺序(使用直接排序算法)。
3、然后再变为n/4个序列(分组数目变少,每组中的数据变多),再排序。
4、不断重复上述过程,随着序列分组变成了一个,数据也完成了排序。
举一个例子来帮助大家理解:现在有一个10个元素的数组:int[] a = {4,6,7,1,2,5,3,9,8,0};
第一步:n=10,n=n/2=5,那也就是说10个元素分成5组,每组两个,组距为5。即4、5一组,6、3一组,7、9一组,1、8一组,2、0一组。
第二步:对这五组数据分别排序:
4<5:不用交换。
6>3:6与3交换(即a[1]=3,a[6] = 6)。
7<9:不用交换。
1<8:不用交换。
2>0:交换(a[5]=0,a[9]=2)
最后的结果为:4,3,7,1,0,5,6,9,8,2
第三步:n = n/2 = 5/2 = 2,将第二步的数组分为2组,每组5个数据,组距为2。即:
第一组:4 7 0 6 8
第二组: 3 1 5 9 2
对每一个分别排序,结果为:
第一组0 4 6 7 8
第二组:1 2 3 5 9
这一步完成后的记过为:0,1,4,2,6,3,7,5,8,9
第四步:n = n/2 = 2/2 = 1。将第三步的数据分成一组(已不用分了)
再对数据进行排序,结果为:0,1,2,3,4,5,6,7,8,9
上述分析过程对应的代码如下,代码可以直接运行,而且对每一步的中间结果都输出了,方便大家查看
/**
* @author Mr0
* describe:使用shell插入排序时,如果原数据已经是基本有序的,则排序的效率可以大大的提高。
* 另外,对于数据量较小的序列使用直接插入排序,因需要移动的数据量较少,其效率也较高。
* 因此shell排序算法具有比较高的排序效率。
*
*/
public class P4_4_Insert_ShellSort {
static final int SIZE =10;
/**
* @return
*/
static int geneNum(){
int tempNum =(int)(Math.random()*100.0);
return tempNum;
}
/**
* @param a
*/
static void shellSort(int[] a){
int r;
int x=0;
for(r=a.length/2;r>=1;r/=2){ //分组,r是组距,也是组数。
for(int i=r;i<a.length;i++){ //在每一组内部利用插入算法排序
int temp=a[i];
int j=i-r;
while(j>=0 && temp<a[j]){
a[j+r] = a[j];
j-=r;
}
a[j+r] = temp;
}
x++;
System.out.print("第"+x+"步排序结果为:");
for(int k=0;k<a.length;k++){
System.out.print(a[k]+" ");
}
System.out.print("r=" + r);
System.out.print("\n");
}
}
public static void main(String[] args){
//int[] array = new int[SIZE];
// for(int i=0;i<10;i++){
// array[i]= P4_4_Insert_ShellSort.geneNum();
// }
int[] array = {4,6,7,1,2,5,3,9,8,0};
System.out.print("排序前的数组为:");
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
System.out.print("\n");
P4_4_Insert_ShellSort.shellSort(array);
System.out.print("排序后的数组为:");
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
}