[閉目洞察算法系列之二]插入排序三種實現
阿新 • • 發佈:2019-01-02
直接插入排序的思想是:將一個待排序的數字按照指定的排序規則,插入到一個前面已經排好序的的子序列中, 從而形成一個新的子序列,等待下一個數字的插入, 直至所有數字排序結束。
假設有陣列a[0 ... n - 1], 排序流程為:
- a[0]位第一個有序子序列, a[1 ... n -1]為無序序列,令i = 1。
- 將a[i]插入到指定位置, 插入後形成a[0 ... i] 有序子序列。
- i++, 重複步驟2, 直至整個陣列有序, 即i == n -1
根據上述思路, 下面寫出程式碼(從小到大排序),
void InsertSortA(int *array, int len) { if (array == nullptr || len < 0) { return; } int curr,before,k; for (int curr = 1; curr < len; ++curr) //遍歷比較 array[1]到 array[len -1] { for (before = curr - 1; before >=0; before--) //遍歷比較待插資料與有序子序列中的元素,尋找比array[curr]小的元素(左面比右面小即停止) { if (array[before] < array[curr]) { break; } } if (before != curr -1) { //遍歷之後發現before未變化,說明array[curr]比子序列最後一個元素都大,那麼當前curr位置就是該插入的位置,比較下一個元素array[curr+1]即可 //如果發現變化了,就說明中間有一個合適的位置,此時就需要將那個位置至子序列末尾的元素全部後移一位,從而將array[curr]插到該位置。 int tmp = array[curr]; for (k = curr - 1; k > before; k--) { array[k +1] = array[k]; } array[k +1] = tmp; } } }
上述程式碼有些囉嗦, 可以將搜尋目標位置與資料後移兩部分合並,即每次先比較array[i]和array[i -1], 若array[i] >= array[i -1], 說明當前元素大於或等於前面子序列中任意元素,則直接跳過,比較下一個元素即可。反之,則進入後移流程: j=i - 1, tmp = array[i], 然後一邊向後移動資料,一邊向前搜尋位置,直至array[j] < tmp, array[j+1] = tmp
void InsertSortB(int *array, int len) { if (array == nullptr || len < 0) { return; } for (int curr = 1; curr < len; ++curr) { if (array[curr] < array[curr-1]) { int tmp = array[curr]; for (before = curr -1; before >=0 && array[before] > tmp; before--) { array[before+1] = arry[before]; } array[before+1] = tmp; } } }
第三種實現的思想是: 將array[j]插入到array[0 ... j-1]步驟進行改寫, 使用資料交換代替資料整體後移。即如果array[j]的前一個數據array[j-1] > array[j], 那麼就將array[j-1]和array[j]交換,然後j--, 直至array[j-1] <= array[j], 從而實現將資料插入效果
void insertSortC(int *array, int len) { if (array == nullptr || len < 0) { return; } for (int curr = 1; curr < len; ++curr) { for (int before = curr -1; before >=0 && array[before] > array[curr]; before--) { swap(before, before + 1); } } } void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; }
參考連結: http://blog.csdn.net/morewindows/article/details/6665714