演算法與資料結構系列 ( 五 ) - 插入排序法改進- Insert Sort

Tim-AutumnWind發表於2020-05-05

前言

可能按照 博文的小夥伴 已經發現了一個問題了,就是在特定情況下。
插入排序 竟然比 選擇排序 的效能還要差。
大家不妨想一下,為什麼?
下面我們找幾個點進行優化

優化一哈

  • 我們在 第二次迴圈 的時候
  • 我們其實是可以把 判斷語句 放入到 迴圈表示式 當中
    /**
    * 插入排序操作方法  - for
    * @param $sort
    * @param $n
    * @return mixed
    */
    function get_insertion_sort_for_simple($sort,$n){
      /** 將資料迴圈一次 */
      for ($i = 0; $i < $n; $i++ ){
          /** 將前面資料進行迴圈,並且帶上判斷的表示式*/
          /** 把 判斷語句 放入到 迴圈表示式 當中 */
          for($j = $i;$j > 0 && $sort[$j] < $sort[$j - 1]; $j--){
              $val = $sort[$j];
              $sort[$j] = $sort[$j - 1];
              $sort[$j - 1] = $val;
          }
      }
      return $sort;
    }

執行後的懵逼

  • 然後,大家發現 哦豁
  • 這樣修改,有一定的優化程度,但是效果並不明顯
  • 然後大家再想想,我們每次進行 位置交換 的時候,是不是需要進行一個以下操作
  • 把需要 修改位置 的值,先賦值給一個 新的變數
      $val = $sort[$j];
  • 再把 交換位置 的值賦值到 修改位置
      $sort[$j] = $sort[$j - 1];
  • 再把 新的變數,放入到 交換位置
    $sort[$j - 1] = $val;
  • 一直這樣迴圈反覆的交換,需要的時間,其實是比 上面?表示式 好使的
  • 因為我們每次交換,那必然是 三次賦值
  • 那麼我們就有了以下思路

插入排序優化版,先簡單瞭解一下思路

  • 首先我們有這麼一段資料,我們需要將他們重新整合有序
    | 7 | 2 | 1 | 5 | 4 | 6 | 9 | 3 | 8 |
第一次排序
  • 此時我們並不會去移動 77已然有序
    | 7 | 2 | 1 | 5 | 4 | 6 | 9 | 3 | 8 |
第二次排序
  • 我們繼續檢視數字座標 1 的數字
  • 這次我們不直接和前面的 7 進行對比交換了
  • 我們直接先把 2 複製出來一份,儲存成新的變數
  • 然後我們再進行一個對比
  • 顯然 27 小,我們就將 7 放在之前 2 的位置
  • 然後我們再對比陣列座標 0 的數字,但是此時已經是座標0,所以我們直接放入即可
    | 2 | 7 | 1 | 5 | 4 | 6 | 9 | 3 | 8 |
第三次排序
  • 我們繼續檢視數字座標 2 的數字
  • 我們還是先把 2 複製出來一份,儲存成新的變數,再進行對比
  • 顯然 17小,我們就將 7 放在之前 1 的位置
  • 然後再拿 12 對比,12 小,我們就將 2 放在之前 7 的位置
  • 此時已經是座標0,所以我們直接放入即可
    | 1 | 2 | 7 | 5 | 4 | 6 | 9 | 3 | 8 |
第四次排序
  • 我們繼續檢視數字座標 3 的數字
  • 我們還是先把 5 複製出來一份,儲存成新的變數,再進行對比
  • 顯然 57小,我們就將 7 放在之前 5 的位置
  • 然後再拿 52 對比,52 大,我們就會跳出迴圈,然後放入即可

TimAutumnWind (轉載請註明出處 learnku.com/users/48310

此後一直以此類推,直至到底

實現一下程式碼 - while

  • 時間和效能記錄,可以參照章節中的 選擇排序
  • 以後會直接實現程式碼
    /**
    * 插入排序操作方法  - while
    * @param $sort
    * @param $n
    * @return mixed
    */
    function get_insertion_sort_while_better($sort,$n){
      $i = 0;
      while ( $i < $n ){
          $j = $i;
          /** 拷貝複製一份 */
          $e = $sort[$i];
          while($j > 0 && $sort[$j - 1] > $e){
              /** 將位置交出,往後挪一個位置 */
              $sort[$j] = $sort[$j - 1];
              $j--;
          }
          /** 跳出迴圈後,放入歸位 */
          $sort[$j] = $e;
          $i++;
      }
      return $sort;
    }
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章