iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Software Development

刷題也算一種電競吧:演算法與資料結構系列 第 13

Day 12 我的回合,抽卡!!! - Insertion Sort

  • 分享至 

  • xImage
  •  

第二個元素開始,往前比對,如果比前一個元素小,則交換位置,以此類推。

[30, 5, 1, 31, 10, 9, 2, 3, 4, 8, 7, 6] 來說:

  • 第一次比對:從第二個元素開始往前比對,5 比 30 小,交換位置:
  • [5, 30, 1, 31, 10, 9, 2, 3, 4, 8, 7, 6]
  • 第二次比對:從第三個元素開始往前比對,1 比 30 小,交換位置,1 比 5 小,交換位置:
  • [1, 5, 30, 31, 10, 9, 2, 3, 4, 8, 7, 6]
  • 第三次比對:從第四個元素開始往前比對,31 比 30 大,順序不變
  • [1, 5, 30, 31, 10, 9, 2, 3, 4, 8, 7, 6]

很像玩撲克牌在整理手牌時會用的方式。

若當前比對不成立時 (像上述範例的第三步驟),代表 31 也不會再比更前面的元素小了,所以可以直接結束該輪比對。

由於此特性,Insertion Sort 很適合用在幾乎快完成排序的資料上。例如某 server 上儲存一組排序過的陣列資料,之後有一筆新資料加進來時,使用 Insertion Sort 可以很快排序完成。

Practice

function insertionSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    let j = i;
    while (j > 0 && arr[j] < arr[j - 1]) {
      [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
      j--;
    }
  }
  return arr;
}

比較白話文的寫法:

function insertionSort(arr) {
  for (let i = 1; i < array.length; i++) {
    for (let j = i; j > 0; j--) {
      if (array[j] < array[j - 1]) {
        let temp = array[j];
        array[j] = array[j - 1];
        array[j - 1] = temp;
      } else {
        break;
      }
    }
  }
  return array;
}

還有另種較好的寫法:

function insertionSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    let temp = arr[i];
    let j = i;
    while (j > 0 && arr[j - 1] > temp) {
      arr[j] = arr[j - 1];
      j--;
    }
    arr[j] = temp;
  }
  return arr;
}
// 以 [1, 3, 5, 7, 11, 13, 9] 來說,
// 在 i 等於 6 的最後一輪比對時,
// 先將當前元素 9 存起來 (temp)
// 9 比 13 小,故 index 6 的位置放 13:[1, 3, 5, 7, 11, 13, 13]
// 繼續比對,9 比 11 小,故 index 5 的位置放 11:[1, 3, 5, 7, 11, 11, 13]
// 繼續比對,9 比 7 大,結束該輪比對,將 temp 放到目前 index 4 的位置,即:[1, 3, 5, 7, 9, 11, 13]

最好情況下,Insertion Sort 的時間複雜度為 O(n)

最壞情況下的時間複雜度為 O(n²)


上一篇
Day 11 選我選我選我選我 - Selection Sort
下一篇
Day 13 只會往前絕不後退 - Singly Linked List
系列文
刷題也算一種電競吧:演算法與資料結構34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言