一圖勝千言,一張動圖又勝過千張靜圖。
學習算法,與其在大部頭的字裏行間咬文嚼字,不如先登高望遠,一覽究竟。
排序是算法里的基礎,有着前輩智慧的結晶。
點擊下圖,你將來到排序算法這座山頂,你可以使用默認設置,也可以稍作修改,然後點擊 “開始排序”, 你將看到看到計算機是如何一步一步將一堆雜亂的數據排好序的。它是如此直觀,你再也不會弄混各種排序算法了。
圖中的 svg 圖形是用 d3 生成的, d3 是前端數據可視化領域的翹楚,推薦!
打開控制臺,裏面的代碼不是醜化過的,一目了然,通俗易懂。只是,這裏用了es6,老瀏覽就oo了。讓該逝去的就逝去吧。
說明
本項目依賴 Rx.js, 這裏用來將排序過程中的中間態數組變成數據流。 如果你還不知道 Rx.js, 強烈推薦,它的數據流思想是在事件循環基礎上的進一步昇華,是一個偉大的工具
const stream$ = Rx.Observable.create(observer => {
try {
const timer = setInterval(() => {
const ret = gen.next()
if (ret.done) {
clearInterval(timer)
observer.complete()
} else {
observer.next(ret.value)
}
}, 0)
return function unsubscribe () {
clearInterval(timer)
}
} catch (err) {
observer.error(err)
}
})
Meta.startTime = +new Date()
Meta.subscription = stream$.subscribe(arr => {
update(arr)
const endTime = +new Date()
document.querySelector('#spendtime').innerHTML = endTime - Meta.startTime
})
generator 是一個可返回多次的函數,如下定義一個 generator:
// 選擇排序
function *selectionSort (arr) {
const len = arr.length
for (let i = 0; i < len - 1; i++) {
let min = i
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[min]) {
min = j
}
}
[arr[i], arr[min]] = [arr[min], arr[i]] // 解構賦值
yield arr
}
}
與函數不同的是,generator 定義時在 function 後面有個 *。
let gen = selectionSort(arr) // 這裏生成了一個generator
let ret = gen.next() // 每次調用generator.next(), yield arr 的arr會賦值給ret.value
gen.next()的返回值是這樣的
{
value: [123, 212, 12, 211, ...],
done: false // or true
}
當 generator 函數體執行完了,done 被置爲 true
當然,這裏的介紹實在只是以管窺豹,唯一的價值是拋磚引玉。推薦阮一峯大神的 ECMA Script 6入門
—done—