希爾排序算法

希爾排序的基本思想java

  ①希爾排序又稱縮小增量排序 ,它本質上是一個插入排序算法。爲何呢?算法

  由於,對於插入排序而言,插入排序是將當前待排序的元素與前面全部的元素比較,而希爾排序是將當前元素  與前面增量位置上的元素進行比較,而後,再將該元素插入到合適位置。當一趟希爾排序完成後,處於增量位置上的元素是有序的。shell

  ②希爾排序算法的效率依賴於增量的選取數組

  假設增量序列爲 h(1),h(2).....h(k),其中h(1)必須爲1,且h(1)<h(2)<...h(k) 。dom

  第一趟排序時在增量爲h(k)的各個元素上進行比較;spa

  第二趟排序在增量爲h(k-1)的各個元素上進行比較;code

  ..........blog

  最後一趟在增量h(1)上進行比較。由此能夠看出,每進行一趟排序,增量是一個不斷減小的過程,所以稱之爲縮小增量。排序

希爾排序的效率和適用場景for循環

  希爾排序的執行時間爲O(N*(logN)2),比快速排序慢(O(N*logN)),比簡單排序快(O(N2))

  希爾排序對於中等規模的數據量的排序是良好的好比1000量級的數據量(親測1000量級立刻排序完成,10000量級等了差很少一分鐘)他的特色是在最壞的狀況和在平均狀況下執行效率基本沒有什麼差異,而快速排序在最壞的狀況下執行效率會很是差,相比較而言,在穩定性上希爾算法更好。

java程序

package sy;

class ArraySh{
    private long[] theArray;
    private int nElems;
    
    public ArraySh(int max)
    {
        theArray = new long[max];
        nElems = 0;
    }
    
    public void inset(long value)
    {
        theArray[nElems] = value;
        nElems++;
    }
    
    public void display(){
        System.out.print("A = ");
        for(int j = 0; j < nElems; j++)
        {
            System.out.print(theArray[j] + " ");
        }
        System.out.println("");        
    }
    //希爾排序方法
    public void shellSort(){
        //定義內循環和外循環變量
        int outer,inner;
        //定義臨時變量存儲插入項
        long temp;
        //定義增量並賦值爲1
        int h = 1;
        //尋找h最大的可能值,也是第一輪第一個數組的第二項,也是第一輪第一個數組的插入項,也是希爾排序的第一個插入項
        while(h <= nElems / 3)
        {
            h = h * 3 + 1;
        }
        //正式開始希爾排序,當h增量爲0時中止希爾排序
        while(h > 0)
        {
            //1.這裏實際上是增量爲h的插入排序,原插入排序增量始終爲1,效率十分低下。            
            //2.在希爾排序的增量h爲1的時候,整個數組其實基本有序了,在基本有序的數組使用插入算法至關高效,這時候的插入排序算法比較和複製的操做不超過兩次
            //3.這層for循環其實在每一輪增量改變後執行,目的是排序小數組,好比增量爲3的數組[12,34,45,21,54,23]被分紅三個小數組,該循環第一輪執行[12,21]的排序,第二輪執行[34,54]的排序,第三輪執行[45,23]的排序
            for(outer = h; outer < nElems; outer++)
            {
                //將插入項賦值給臨時變量
                temp = theArray[outer];
                //將內外循環鏈接
                inner = outer;
                //判斷插入項的插入位置  條件是插入項和前面的有序部分比較並且小,而且inner大於0
                while(inner > h -1 && theArray[inner - h] >= temp)
                {                    
                    //比插入項大的有序部分所有後移一位
                    theArray[inner] = theArray[inner - h];
                    inner -= h;
                }
                //把插入項發在比它大的數據項的位置
                theArray[inner] = temp;            
            }
            //增量h減小
            h = (h - 1) / 3;        
        }
    }
}
class App{
    public static void main(String[] args)
    {
        int maxSize = 10;
        ArraySh arr;
        arr = new ArraySh(maxSize);
        
        for(int j = 0 ; j < maxSize; j++)
        {
            long n = (int)(java.lang.Math.random() * 99);
            arr.inset(n);
        }
        arr.display();
        arr.shellSort();
        arr.display();        
    }
}
相關文章
相關標籤/搜索