原理: 透過重複走訪要排序的數列,一次比較兩個元素,如果順序錯誤就交換。
複雜度:O(n2)
原理: 透過重複走訪要排序的數列,一次比較兩個元素,如果順序錯誤就交換。
複雜度:O(n2)
原理: 每一次從待排序的資料中選出最小的一個元素,存放在序列的起始位置,直到全部排完。
複雜度: \( O(n^2) \)
原理: 將陣列分為「已排序」和「未排序」兩部分,每次從未排序中取出一個元素,插入到已排序部分的適當位置。
複雜度:O(n2)
原理: 採用分而治之法。將大問題分成小問題(不斷將陣列切半),解決小問題(當陣列只剩一個元素時視為已排序)後,再將結果合併(Merge)。
時間複雜度: 始終是 $O(n \log n)$。無論資料原本多亂,它的效能都非常穩定且優秀。在處理大量數據時,它比 $O(n^2)$ 的演算法快非常多。
空間複雜度: $O(n)$。由於合併時需要額外的空間來暫時存放拆開的陣列,因此它比氣泡或插入排序更吃記憶體。
穩定性: 穩定 (Stable)。在合併過程中,若遇到數值相同的元素,會優先處理左側元素,確保原始順序不變。
原理: 挑選一個「基準點」(Pivot),將比基準點小的排在左邊,比基準點大的排在右邊,再對左右兩邊重複此動作(遞迴)。
時間複雜度: 平均 $O(n \log n)$,最壞情況下為 $O(n^2)$(當基準點選得不好時)。
空間複雜度: $O(\log n)$,主要是遞迴呼叫堆疊產生的開銷。
穩定性: 不穩定 (Unstable)。因為交換是跨越式的,相同數值的順序可能會被打亂。
下表整理了本報告中實作的五種排序演算法之效能對比:
| 演算法 | 最佳時間 | 平均時間 | 最壞時間 | 空間複雜度 | 穩定性 |
|---|---|---|---|---|---|
| 氣泡排序 | $O(n)$ | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 穩定 |
| 選擇排序 | $O(n^2)$ | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 不穩定 |
| 插入排序 | $O(n)$ | $O(n^2)$ | $O(n^2)$ | $O(1)$ | 穩定 |
| 合併排序 | $O(n \log n)$ | $O(n \log n)$ | $O(n \log n)$ | $O(n)$ | 穩定 |
| 快速排序 | $O(n \log n)$ | $O(n \log n)$ | $O(n^2)$ | $O(\log n)$ | 不穩定 |
以前只知道 $O(n \log n)$ 比 $O(n^2)$ 快,但透過這次的 JavaScript 視覺化實作,我親眼看到當資料量增加時,氣泡排序與插入排序在畫面上的遲鈍,對比合併排序與快速排序那種俐落感。這讓我明白在處理海量數據時,選擇正確的演算法是多麼關鍵。
實作合併排序時,遞迴的概念起初讓我感到挫折,但在成功將陣列拆解並重新合併後,我對遞迴邏輯有了全新的認識。