插入排序之直接插入排序算法

一、什麼是插入排序算法

它的工做原理是經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。數組

從第二個元素開始r[1],那麼將他左邊的元素做爲一個已經有序的序列,將r[1]按從小到大的順序插入到函數

有序序列中的合適位置使之成爲一個新的有序序列;接着將r[2]插入到左邊的有序序列中,使之成爲一個spa

新的有序序列,依次類推,直道將全部的元素都遍歷完了以後,那麼整個數組就是一個從小到大的有序數組了。3d

 

二、效果演示指針

        這是須要進行排序的序列code

         對於第1個元素8來講,它自己就是有序的blog

         再來考慮第2個元素6,由於他比8小,交換一次位置排序

     

        再來考慮第3個元素2,由於他比8小,交換一次位置class

        2又比左邊的6小,交換一次位置

          再來考慮第4個元素,由於他比8小,交換一次位置

       3又比左邊的6小,交換一次位置

       3比左邊的2大,不需交換,前4個元素就已經排序完畢,後面的依次類推

 

二、時間複雜度

O(n^2)

 

三、算法實現(基於C++)

 1 /* 直接插入排序算法實現 */
 2 template<typename T>
 3 void insertSort(T a[], int count)
 4 {
 5     /* 找到a[i]這個元素的合適插入位置,由於第一個元素前面沒有元素,沒法進行比較,因此從第二個元素開始 */
 6     for (int i = 1; i < count; i++) {
 7         for (int j = i; j > 0 && a[j - 1] > a[j]; j--) {  
 8             std::swap(a[j-1], a[j]);
 9         }
10     }
11 }

 

四、直接插入算法的改進

從上面的算法實現上可知,咱們的直接插入排序算法上須要進行大量的兩個元素交換的動做(swap函數),而兩個元素交換在實現上是須要進行3次的賦值操做,因此會給整個過程形成大量的時間浪費,因此咱們將對上面在算法的實現上進行一個改進,經過改進以後能夠大大的縮短直接插入排序算法的所須要的時間。

改進的思想: 其實就是經過直接的賦值操做代替大量的數組元素間的互換操做,具體的實現請看下面的演示

 首先仍是從第2個元素開始排序,此次咱們先將6這個元素拷貝出來一份,然

                                      後再與左邊的8進行比較,6副本比8小,將8往右移動,再將6副本指針往左移動

 

  直接將6副本賦值給當前所指向的這個位置,此時前面2個元素排序完畢

 

       

 

   考慮第3個元素,仍是先將其複製一份,2副本比左邊的8小,將8往右移動,

                                       將2副本指針往左移動

 

   2副本又比左邊的6小,將6往右邊移動一次,將2副本指針往左移動

 

  直接將2副本賦值給當前所指向的這個位置

 

  前面3個元素排序完畢

 

  再來考慮第4個元素,首先仍是先將其拷貝一份,3副本比左邊的8小,直接

                                       將8往右移動,將3副本指針往左移動

 

  3副本又比左邊的6小,將6往由移動,3副本指針往左移動

 

  此時3副本比左邊的2大,這個位置合適,將3副本賦值給當前所指向的這個位置

 

  至此前面的4個元素排序完畢,依次類推

 

由此能夠知道通過上面的方法以後,減小了兩個元素之間的交換操做,大大縮短了時間。

算法的實現以下:

 1 /*********************************** 直接插入排序算法實現 ********************************/
 2 template<typename T>
 3 void insertSort (T a[], int count)
 4 {
 5     /* 找到a[i]這個元素的合適插入位置,由於第一個元素前面沒有元素,沒法進行比較,因此從第二個元素開始 */
 6     for (int i = 1; i < count; i++) {
 7         int j;
 8         T copy = a[i];           // 將須要插入到左邊有序序列的元素拷貝出來做爲一個副本
 9         for (j = i; j > 0 && a[j - 1] > copy; j--) { 
10             a[j] = a[j - 1];     // 若是條件知足,直接前一個元素賦值給後面的元素
11         }
12         a[j] = copy;             //  找到該元素的合適位置以後直接賦值便可
13     }
14 }
15 /**********************************************************************************************/

咱們將一系列的元素之間的交換變成了賦值操做,大大的縮短了排序所須要的時間,能夠大大提升程序運行的效率。

 

五、總結

(1)插入排序的時間複雜度是O(n^2)級別

(2)插入排序的內層循環是能夠提早終止的,由於只要找到了合適的位置,將元素插入到該位置後就能夠終止本次循環了。

(3)若是須要進行排序的數組序列原本就是一個很是有序的狀態,那麼插入排序執行起來的效果將比選擇排序快上不少,由於插入排序的內層循環將大大的減小時間,而選擇排序內層循環每一次都會循環到底,因此在時間上將遠遠超過插入排序,因此當須要排序的數組序列原本就是一個很是有序的狀態,那麼內層的循環基本上不用作了,這樣會大大提高效率。當須要進行排序的序列幾乎接近於有序時,插入排序的時間複雜度將會變爲n級別。

相關文章
相關標籤/搜索