面試常備題—插入排序

來源:互聯網
上載者:User

      排序演算法是最常見的筆試題目,幾乎所有的筆試和面試都會考到,因為它體現的就是程式員的演算法基礎。可惜的是,作為一名菜鳥,而且還是即將面臨畢業的大三菜鳥,這方面的修養還真是不足,所以,在這裡整理一下自己收集到的排序基礎知識,以備需要的時候可以查閱。

      先介紹插入排序。

1.直接插入排序

      直接插入排序(straight insertion sort)的原理是這樣的過程:

      每次從無序表中取出第一個元素,把它插入到有序表的合適位置,使有序表仍然有序。實際的過程像是這樣:

      對於序列:46 58 15 45

      第一次:[46] 58 15 45

      第二次:[46 58] 15 45

      第三次:[15 46 58] 45

      第四次:[15 45 46 58]

      正如上面數列的排序過程,我們知道,直接插入排序時間複雜度是O(n * n)(即平均時間複雜度),屬於穩定的排序(所謂穩定,就是原本序列中兩個相同的元素,在排序後仍然維持原本的排列)。空間複雜度為O(1)。

      考慮到要實現的排序演算法很多,為了方便我的測試,我專門定義了一個Sort介面和一個測試類別:

public interface Sort {  void sort(int[] arr);}public class SortTest {   public static void main(String[] args){       int[] arr = {46, 58, 15, 45, 90, 18, 10, 62};       execute(new DirectInsertSort(), arr);       for(int element : arr){           System.out.println(element);       }   }    public static void execute(Sort sort, int[] arr){       sort.sort(arr);   }}

        下面就是直接插入排序的java代碼:

public class DirectInsertSort implements Sort {    @Override    public void sort(int[] arr) {        int len = arr.length;        int temp = 0;        int j = 0;
for(int i = 0; i < len; i++){ temp = arr[i]; for(j = i; j > 0 && temp < arr[j - 1]; j--){ arr[j] = arr[j - 1]; } arr[j] = temp; } }}

      直接插入排序是有兩層嵌套迴圈組成的,外層迴圈標識待比較的元素,內層迴圈為待比較元素確定其最終位置。注意一點,我們必須為待比較元素留一個儲存空間,因為我們在每次排序後都需要將待比較元素插入比它小的元素的後一位。

      直接插入排序的優點就是穩定和快,尤其是序列的有序程度越大,它就越快。但是缺點依然很明顯,就是序列如果是完全無序,並且數列非常大,那麼比較的次數就會是一個可怕的數字,並且元素的移動非常頻繁。當然,解決這樣的問題可以使用鏈表,因為鏈表的優點就是方便元素的插入和移動,但是有一種排序就是為瞭解決這種問題。

2.希爾排序(Shell)

      希爾排序是對直接插入排序的改進,該方法又稱為縮小增量排序。它的基本思想紮根於直接插入排序的特點:每次插入一個元素,使有序序列只增加1個節點,並且對插入下一個元素沒有提供任何協助。於是,就有一個叫希爾的人提出這樣的想法:將要排序的數列按照某個增量d分成若干組,每組中元素的下標相差d,接著對每組中全部元素進行排序,然後用一個較小的增量對它進行分組和排序。當增量減到1時,整個要排序的數列就被分成一組,排序也就完成。

      這種改進是為了消除直接插入排序中大量元素交換移動的問題。增量序列的選擇是個重要問題,它必須滿足下列條件:

(1)最後一個增量必須為1;

(2)應盡量避免序列中的元素,尤其是相鄰元素互為倍數的情況。

      一般情況下,每次增量的選擇都取序列的一半,直到增量為1。

      還是之前那個序列:46 58 15 45,用希爾排序進行排序:

      假設增量為2,第一次的分組結果為:[46, 15], [58, 45]

      然後我們在每組中進行直接插入排序:[15, 46], [45, 58]

      然後增量遞減為1,同樣適用直接插入排序,但是序列的有序程度已經大大增強,非常快就搞定了序列的排序。

      [15, 46, 45, 58] ——>[15, 45, 46, 58]

      上面的增量序列算是比較簡單的,但是它違背了我們上面的要求:增量序列中相鄰元素互為倍數的情況,我們再用一個大一點的數列來示範這個問題:

      序列為:46, 58, 15, 45, 90, 18, 10, 62

      假設增量序列為:4, 2, 1,排序的結果如:

      [46, 90], [58, 18], [15, 10], [45, 62]  ——>[46, 90], [18, 58], [10, 15], [45, 62]

      [46, 18, 10, 45], [90, 58, 15, 62] ——>[10, 18, 45, 46], [15, 58, 62, 90]

      [10, 18, 45, 46, 15, 58, 62, 90] ——>[10, 15, 18, 45, 46, 58, 62, 90]

      假設增量序列為:3, 1,排序的結果如:

      [46, 45, 10], [58, 90, 62], [15, 18] ——>[10, 45, 46], [58, 62, 90], [15, 18]

      [10, 45, 46, 58, 62, 90, 15, 18] ——>[10, 15, 18, 45, 46, 58, 62, 90]

      可見,選擇第二種增量序列,最後增量為1時,序列的有序程度更高,所以效率更快。

      如何選擇增量序列才能讓排序更快,這個問題至今沒有統一的答案,我自己收集到的資料就介紹了這樣的情況:增量序列h = n / 3 + 1, n / 9 + 1, n / 27 + 1,..., 1。

      如果序列比較小,討論這個問題其實很多餘,因為它們運行起來的速度幾乎是沒有什麼差異。所以,一般情況下,選擇折半的增量序列就已經滿足要求了,而且在編程上更加方便。

      希爾排序的時間複雜度最好情況下為O(n * logn),但它並不是一個穩定的排序,因為增量序列的選擇對它的影響非常大。空間複雜度為O(1)。

      希爾排序的java代碼如下:

public class ShellSort implements Sort {    @Override    public void sort(int[] arr) {        int step = arr.length / 2;        int tmp = 0;        while (step >= 1) {            for (int i = 0, len = arr.length; i < len; i++) {                for (int j = i; j < len; j += step) {                    if (arr[i] > arr[j]) {                        tmp = arr[i];                        arr[i] = arr[j];                        arr[j] = tmp;                    }                }            }            step = step / 2;        }    }}

        

     

      

     

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.