前端工程師算法系列(1)-氣泡排序
前言
對於非科班出身的程式員特別是前端工程師來說,演算法的確實是一塊心病。買一本演算法導論來擼幾個月同時還得學一門新語言既難以施行,也極度缺乏價效比。
所以我打算以演算法為主題出一個系列專輯,以廣大前端程式設計師熟悉的 JavaScript 為範例語言,用通俗的語言講解常見演算法,儘量儘可能多的覆蓋前端工程師遇到的演算法面試題。
本人自知才疏學淺,所以科學、全面、規範、嚴謹一律不管,但我會盡量用通俗的語言和程式碼讓缺乏演算法概念的人快速理解演算法。
如果你覺得不錯,或者發現文章中的錯誤,或者有更好的建議,歡迎演算法交流群交流,點此掃碼進群。
後續文章中會涉及:常見排序演算法、常見搜尋演算法、樹、分治法、動態規劃、貪心演算法等
氣泡排序
一、原理解析
選擇第1個和第2個數字,如果第1個>第2個二者交換位置(假設是升序排列)。之後選擇第2個和第3個數字,類似交換處理。一輪下來後,最大的數字會“冒泡”到最後一位。
接下來,忽略已經拍好的數字,對於剩下的數字再來一輪
...
直到所有的數字都排列完成。
二、範例演示
以下表格里,紅色表示選中的待排序的數字,粗體表示本輪剛剛排列過的數字,藍色表示最終排好的數字。
第一輪:
- 選擇 10 和 34, 進行比較, 其中 10 < 34, 二者不需要交換
- 選擇 34 和 21, 進行比較, 其中 34 > 21, 二者需要交換
- 選擇 34 和 47, 進行比較, 其中 34 < 47, 二者需不要交換
- 選擇 47 和 3, 進行比較, 其中 47 > 3, 二者需要交換
- ...
- 最後 47 交換到末尾
第二輪:
忽略已經排列好的47, 按照剛剛的邏輯再次排序
...

三、實現方式
function bubleSort(arr) { for(let i = 0; i < arr.length /*i代表輪數*/; i++) { for(let j = 0; j < arr.length - i /*j代表當前輪選中的元素下標*/; j++) { if(arr[j] > arr[j+1]) { [ arr[j], arr[j+1] ] = [ arr[j+1], arr[j] ] /*交換元素*/ } //console.log(arr) } } } var arr = [10, 34, 21, 47, 3, 28] bubleSort(arr) console.log(arr)
四、效率測試
下面我們測試排序效能。以下的程式碼中,randomArr 函式會生成一個隨機陣列, 陣列長度預設是100, 最大值預設值是1000。 console.time 和 console.end 用來記錄排序時間。
let arr = randomArr(10000, 100) console.time('bubleSort') bubleSort(arr) console.timeEnd('bubleSort') function randomArr( arrLen = 100, maxValue = 1000 ) { let arr = [] for(let i = 0; i < arrLen; i++) { arr[i] = Math.floor((maxValue+1)*Math.random()) } return arr } function bubleSort(arr) { for(let i = 0; i < arr.length; i++) { for(let j = 0; j < arr.length - i; j++) { if(arr[j] > arr[j+1]) { [ arr[j], arr[j+1] ] = [ arr[j+1], arr[j] ] /*交換元素*/ } } } }
經測試100次取平均值,得出初步結論:測試陣列長度增加10倍,排序時間約增加100倍
複雜度分析
時間複雜度(可以理解為排序的次數)計算: (n-1) + (n-2) + ... + 1 = n*(1 + (n-1))/2,所以時間複雜度為 O(n^2) ,和上面的測試基本一致。
如果你覺得不錯,或者發現文章中的錯誤,或者有更好的建議,歡迎演算法交流群交流,點此掃碼進群。