已经总结了3种简单的基本排序算法,现在开始讲的是一些复杂,但是更高效,在数据量大时速度明显更快的一些排序算法,首先讲的是希尔排序。
一.算法思路
希尔排序又称为“缩小增量排序”,是一种插入排序类的算法。
考虑先排序部分原始数组,在它们至少局部有序的情况下去排序整个数组。子数组有序将比初始情况更接近整体有序的最好情况。
思路:选择第一个增量d1<n,把全部记录按此值从第一个记录分组,所有距离为d1的记录为一组。在各组内进行插入排序;然后缩小间隔,取第二个增量d2<d1;重复,直到di=1为止,即把所有记录放在同一组内排序。
特点:每次以不同的增量进行插入排序。到最后一趟排序时,许多记录已经有序,不需要多少移动。希尔排序是不稳定的排序方法。
(稳定性概念:两个相同的值,排序前后的顺序不变;稳定的重要性:交换元素存在开销,按照基数排序,不稳定排序无法完成基数排序。当对基本数据类型的元素进行排序时,使用不稳定的排序方法;非基本数据类型时,则使用稳定的排序方法。)
(感觉稳定性的理解很重要,后面写一篇来总结一下所有算法的稳定性)
二.伪代码
把a分为h个子数组;
for i=1 to h
排序子数组i;
排序总数组。
三.代码实现
/**
* @author garypotter
* @version 创建时间:2016年4月2日 下午4:12:17
* @TODO
* 类说明
*/
public class ShellSort {
public static void main(String[] args) {
Object[] a={5,2,3,8,1,9,10,13,4,11};
shellsort(a);
System.out.println("result:"+a[0]+" "+a[1]+" "+a[2]+" "+a[3]+" "+a[4]+" "+a[5]+" "+a[6]+" "+a[7]+" "+a[8]+" "+a[9]);
}
public static void shellsort(Object[] a){
int i,j,k,h,start;
int increments[]=new int[20];
//根据a的大小计算增量并存入数组
for(h=1,i=0;h<a.length;i++){
increments[i]=h;
h=3*h+1;
}
//最外面的循环控制增量的变化,从最大的增量依次变小,最终为1
for(i=i-1;i>=0;i--){ //注意i-1这一句,因为上面的i在判断是否超出之前就已经i++了,所以其实应该最后一个元素应该从i-1开始
h=increments[i]; //获取增量的值,即同一组的间隔值,增量从大到小取出
System.out.println(h);
for(start=h;start<2*h;start++){//增量为h,表示分为h个子数组来排序,h在此处不会变了
//start从h到2h,是不同组的第二个元素!!!
//插入排序开始
for(j=start;j<a.length;){ //其实这个start不是第一个元素,而是第二个元素
Comparable tmp=(Comparable) a[j];//这个就是待插入的值,来进行比较,首先插入的就是第二个元素!!!!
k=j;
while(k-h>=0&&tmp.compareTo(a[k-h])<0){
//k-h>=0表示还有前一个元素
a[k]=a[k-h];
k=k-h;
}
a[k]=tmp;
j+=h;
}
//插入循环结尾
}
}
}
}