對於經典算法,你是否也遇到這樣的情形:學時以爲很清楚,可過陣子就忘了?javascript
本系列文章就嘗試解決這個問題。java
研讀那些排序算法,細品它們的名字,其實都很貼切。算法
好比基數排序,就是按照數字的「位」來排序。數組
位,是進位的位,好比十進制數的基數是10,就能夠按照個十百千萬等位來排序。post
上圖演示了基數排序算法的整體流程。先按個位從小到大排序,而後再按十位、百位排序。只要排序算法是穩定的,那麼最後總體就是有序的。爲了方便看出數字的每一位具體是多少,這裏對位數少的數字進行了左邊補0。性能
可見該算法的核心在於選擇的排序算法是穩定的。ui
排序是穩定的意思說,排序後,其相同元素的相對順序並不會改變。好比19和18,按個位排,9大於8,於是順序是1八、19。兩者十位上的數值相等(都爲1),若是此時排十位的算法是不穩定的話,會可能出現19在前,18在後這樣的情形,那麼以前先按個位排序的意義將不復存在了。spa
瞭解了總體原理後,咱們來一步步寫出它。3d
首先,如何判斷數字最長有多少位?遍歷一遍就能解決:code
let array = [666, 520, 36, 49, 9, 600, 8, 502, 998, 32]
let maxLength = 0
for (let v of array) {
let length = String(v).length
if (length > maxLength) {
maxLength = length
}
}
console.log(maxLength) // 3
複製代碼
這裏咱們取巧,經過轉化爲字符串,來獲取每一個數字的位數。也能夠經過,找到最大數,用它不斷除以10來獲取位數。
另外一個問題是:如何獲取數字某位上的數字呢?
好比獲取36的百位上的數字,經過轉字符串後,補0取第一位:
String(36).padStart(maxLength, '0')[0] // 0
複製代碼
有了上述鋪墊後,總體邏輯就有了:
for (i = 0; i < maxLength; i++) {
array = sort(array, i)
console.log(array)
}
複製代碼
對數組排序三次,每一次的輸出做爲下一次的輸入。其中sort方法只要是穩定的排序算法便可。
這裏推薦使用桶排序算法,下面咱們簡單過一遍。
因爲個位上的數值範圍是從0到9,須要構建10個桶:
let buckets = []
for (let i = 0; i < 10; i++) {
buckets.push([])
}
複製代碼
而後把按個位上的數值把元素分別分到這些桶裏:
for (let v of array) {
let pad = String(v).padStart(maxLength, '0')
let num = pad[maxLength -1]
buckets[num].push(v)
}
console.log(buckets)
// [ [ 520, 600 ], [], [ 502, 32 ], [], [], [], [ 666, 36 ], [], [ 8, 998 ], [ 49, 9 ] ]
複製代碼
由於桶的區間大小特殊(爲1),所以桶內部不需再排(有點計數排序的意味)。直接按順序輸出每一個桶的元素便可:
let result = []
for (let bucket of buckets) {
result.push(...bucket)
}
console.log(result)
// [ 520, 600, 502, 32, 666, 36, 8, 998, 49, 9 ]
複製代碼
sort方法完整代碼是:
function sort(array, index) {
let buckets = []
for (let i = 0; i < 10; i++) {
buckets.push([])
}
for (let v of array) {
let pad = String(v).padStart(maxLength, '0')
let num = pad[maxLength - 1 - index]
buckets[num].push(v)
}
let result = []
for (let bucket of buckets) {
result.push(...bucket)
}
return result
}
複製代碼
至此,基數排序原理和實現已經說完了。查看完整代碼:codepen。
須要補充的是,基數排序也有從高位開始遍歷的。另外,用它也能夠輕鬆實現字典排序。
這裏總結一下,基數排序的性能,取決於內部排序算法的選擇。若是使用桶排序,時間複雜度爲O(k*n),其中k爲最大元素的位數,通常都是很小數。
基數排序,要作到能分分鐘手寫出來,是須要掌握其排序原理的。核心是使用穩定排序從低位逐次排列到高位,一旦理解就容易寫出來,不須要死記硬背的。
但願有所幫助,本文完。
本系列已經發表文章: