對於經典演算法,你是否也遇到這樣的情形:學時覺得很清楚,可過陣子就忘了?
本系列文章就嘗試解決這個問題。
研讀那些排序演算法,細品它們的名字,其實都很貼切。
比如選擇排序,所謂“選擇”,就是每次遍歷時,選擇一個最小的交換到已排好序列的後面。
上圖演示了第三次遍歷,此時元素1和2已經排好序,再在剩下的元素中找到最小的元素3,然後與目標位置交換。
可以看出該演算法的核心是:如何在未排好序的元素中找到最小的元素?
這一點難不倒我們,熊瞎子劈苞米,搞個變數記錄最小下標。
let array = [1, 2, 4, 5, 3]
let minIndex = 2
for (let i = 2; i < array.length; i++) {
if (array[minIndex] > array[i]) {
minIndex = i
}
}
console.log(minIndex) // 4
複製程式碼
找到了最小元素,然後再與目標位置的資料進行交換即可(如果恰好正在目標位置就不用交換了):
if (minIndex !== 2) {
swap(array, 2, minIndex)
}
console.log(array) // [1, 2, 3, 5, 4]
複製程式碼
其中swap函式封裝了兩個元素如何交換:
function swap(array, i, j) {
[array[i], array[j]] = [array[j], array[i]]
}
複製程式碼
每次遍歷都排好一個最小的,n次遍歷就能排好所有,可以輕鬆寫出程式碼:
let array = [4, 5, 3, 2, 1]
for (let j = 0; j < array.length; j++) {
let minIndex = j
for (let i = j; i < array.length; i++) {
if (array[minIndex] > array[i]) {
minIndex = i
}
}
if (minIndex !== j) {
utils.swap(array, j, minIndex)
}
}
複製程式碼
完整流程示意如下:
上述程式碼,還有優化的空間,比如只需要遍歷n-1次就行了,因為最後一次,必然剩下了一個元素,不需要再做處理。檢視完整程式碼:codepen。
至此,選擇排序原理和實現已經說完了。
這裡總結一下,選擇排序不需要額外空間,是本地排序,相等元素是不會交換前後順序,因而也是穩定排序,時間複雜度為O(n^2),適用於少量資料排序,但實際中用得不多。
選擇排序,要做到能分分鐘手寫出來,是需要掌握其排序原理的。每次遍歷核心是找到最小元素然後與目標位置交換即可,一旦內層遍歷能寫出來,那麼整體就很容易寫出來,不需要死記硬背的。
希望有所幫助,本文完。
本系列已經發表文章: