希爾排序因計算機科學家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為止。
需要指出的是,實際的計算中不沒有完全按照以上的排序順序,具體看圖示:
代碼 :
Code:
- 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;
- }
- }
- }
Code:
- package highSort;
- public class ShellSortApp {
- 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個整數,進行希爾排序。