插入排序的升级版之希尔排序

来源:互联网 发布:pr是什么软件怎么用 编辑:程序博客网 时间:2024/04/29 01:23

希尔排序采用分组的思想,分组后,对组内元素进行插入排序处理。下面结合代码进行描述:

void shellsort(int arr[],int length){int i,j,k;int increasment=length;int temp;do{increasment=increasment/2;for(i=increasment;i<length;i++){if(arr[i]<arr[i-increasment]){ temp=arr[i];for(j=i-increasment;j>=0 && temp<arr[j];j-=increasment)arr[j+increasment]=arr[j];arr[j+increasment]=temp;}}}while(increasment>0);}
这里定义增量变量increasment,采用每次减半的方式生成增量序列。到底怎么生成增量序列,使得算法高效是一个数学难题,对这方面感兴趣的童鞋可以仔细研究下~

我们假设待排序的数组大小为20。

第一次分组:increasment=10,也就是分为10组,每组只有两个元素。第一组由数组的第1个元素与第11个元素组成,第二组由数组的第2个元素与第12个元素组成。以此类推,第十组由数组的第10个元素与第20个元素组成。然后开始对每一组进行插入排序。

第二次分组:increasment=5,分为五组,每组四个元素。第一组为数组元素的第1个,第6个,第11个,第16个。第二组为数组元素的第2个,第7个,第12个,第17个。以此类推,第五组是数组元素的第5个,第10个,第15个,第20个。

到这里了,有必要对分组的特点进行探索。

首次分组的时候,为(1,11),(2,12)...(10,20),第二次分组,为(1,6,11,16),(2,7,12,17),..,(5,10,15,20)。

可以明显地看出来,分组后的组内元素两两之间的差值为本次的increasment。

所以总的数组元素数N除以分组组数increasment等于每组的元素数M,每组相邻元素之间的差值等于increasment。

有了上面的结论,那么下面对第三次分组的情况:increasment=2. N=20.M=10.分组情况:(1,3,5,7,9,11,13,15,17,19),(2,4,6,8,10,12,14,16,18).

所以我们每次关注的插入其实就是当前的i与i-increasment所对应的元素的进行比较插入,使得每次分组的元素有序。

然后当increasment=0的时候,执行一次直接插入,完成排序。

以上就是我对希尔排序的理解,有人可能会疑惑,希尔排序对性能提升有多少呢?这个是依照增量序列的选取而定。一般情况下,希尔排序的性能要好于前面讲到的三种简单的排序算法。因为希尔排序按照increasment取值的不同进行跳跃式前进,经过几次分组排序后,序列达到基本有序,小的元素在前面,大的元素在后面,不大不小的元素在中间。这样最后进行直接插入排序的时候,可以极大地减少操作的次数。从文献资料中查得,当增量序列为2的t-k+1次方减1时候,这里(0<=k<=[log(n+1)])时,算法的复杂度可以达到n的(3/2)次方。



0 0
原创粉丝点击