希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法。希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插入排序的执行效率。希尔排序算法的代码短而简单,而且它在最坏情况下的执行效率和在平均情况下的执行效率相比没有差很多。
插入排序算法:插入排序算法在执行到中间的时候,标记符指向的数的左边都是有序的,而标记右边的都是没有排序的。这个算法取出标记符指向的数据项,从其左边第一个数据项开始从右到左扫描,凡是比它大的数字都右移一位,最后插入。插入排序的问题是,假设一个很小的数据项在很靠近右边的位置上,在移动这个数据项的过程中要复制太多中间数据项,平均每个数据移动复制达N/2,插入排序执行效率为O(N2).
如果某个算法能够不必一个一个移动所有中间数据项,就能把较少的数据项移动到左边,那么这个算法的执行效率就有很大的改进。
希尔排序就是基于这种思想设计的。
希尔排序引入N-增量排序的概念,上图所示的为增量为4时的排序,即只对0,4,8排序,间隔为4.这步操作完成后指针右移一位对1,5,9排序,然后对2,6排序,最后是3,7排序。形成彼此交错互相独立的排序。
减少间隔:当完成了间隔为4个排序后,再接着做间隔为1的插入排序,完成后则整个数组都会有序了。这个缩减间隔序列的数值是由knuth序列决定,即是公式3h+1序列(1,4,13,40,。。。)保证3h+1<maxItems(数组中数据项个数)得到最大的h值,然后按照h=(h-1)/3递减,直到h=1为止。
需要指出的是,实际的计算中不没有完全按照以上的排序顺序,具体看图示:
代码 :
- package highSort;
- //demonstrate shell sort
- //
- class ArraySh
- {
- private long[] theArray; //ref to array theArray
- private int nElems; //number of data items
- //-------------------------------------------------------------
- public ArraySh(int max) {
- theArray=new long[max];
- nElems=0;// TODO Auto-generated constructor stub
- }
- //------------------------------------------------------------
- public void insert(long value) //put element into array
- {
- theArray[nElems]=value; //insert it
- nElems++; //increment size
- }
- //-------------------------------------------------------------
- public void display() //display each items of the array
- {
- System.out.print("A=");
- for(int j=0;j<nElems;j++)
- System.out.print(theArray[j]+" ");
- System.out.println(" ");
- }
- //-------------------------------------------------------------
- public void shellSort()
- {
- int inner=0,outer=0;
- long temp=0;
- int h=1; //find initial value of h
- while(h<=nElems/3) //1,4,13,40,121,...
- h=h*3+1;
- while(h>0)
- {
- for(outer=h;outer<nElems;outer++)
- {
- temp=theArray[outer];
- inner=outer;
- while(inner>h-1&&theArray[inner-h]>=temp)
- {
- theArray[inner]=theArray[inner-h];
- inner-=h;
- }
- theArray[inner]=temp;
- }
- h=(h-1)/3;
- }
- }
- }
- package highSort;
- public class ShellSortApp {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- int maxSize=1000;
- ArraySh arr;
- arr=new ArraySh(maxSize);
- for(int j=0;j<maxSize;j++)
- {
- long n=(int)(java.lang.Math.random()*1500);
- arr.insert(n);
- }
- arr.display();
- arr.shellSort();
- arr.display();
- }
- }
随机生成1000个整数,进行希尔排序。