📊 6 種演算法 · 各自獨立設定 · 逐步視覺化

排序演算法視覺化

每個演算法都有獨立的柱子數量、播放速度與操作按鈕,互不影響。

或在各演算法區域分別設定
冒泡排序Bubble Sort
⏱ 均攤 O(n²)💾 O(1)✅ 穩定

反覆比較相鄰元素,若順序錯誤則交換,最大值像泡泡浮向末端。

520
步驟 1 / 0
選擇排序Selection Sort
⏱ 均攤 O(n²)💾 O(1)❌ 不穩定

每輪從未排序區掃描找出最小值,交換至已排序區末端。

520
步驟 1 / 0
插入排序Insertion Sort
⏱ 均攤 O(n²)💾 O(1)✅ 穩定

逐一取出元素,插入左側已排序序列的正確位置,如同整理手牌。

520
步驟 1 / 0
快速排序Quick Sort
⏱ 均攤 O(n log n)💾 O(log n)❌ 不穩定

選取 Pivot,小於放左、大於放右,遞迴分治左右子序列。

520
步驟 1 / 0
合併排序Merge Sort
⏱ 均攤 O(n log n)💾 O(n)✅ 穩定

分治法:遞迴對半拆分至單一元素,再將有序子序列兩兩合併。

520
步驟 1 / 0
堆積排序Heap Sort
⏱ 均攤 O(n log n)💾 O(1)❌ 不穩定

先建立最大堆積,重複取出堆頂(最大值)並重整堆,直到排序完成。

520
步驟 1 / 0
比較中
交換中
Pivot
當前最小
已就位
未處理

📊 複雜度對照表

演算法平均時間最壞時間空間穩定
冒泡排序O(n²)O(n²)O(1)
選擇排序O(n²)O(n²)O(1)
插入排序O(n²)O(n²)O(1)
快速排序O(n log n)O(n²)O(log n)
合併排序O(n log n)O(n log n)O(n)
堆積排序O(n log n)O(n log n)O(1)

❓ 常見問題

O(n²) 和 O(n log n) 的效率差距有多大?

以 n=1,000 為例:O(n²) 約 1,000,000 次操作;O(n log n) 只需約 10,000 次,差了 100 倍。n=1,000,000 時差距更達萬倍。

快速排序最壞是 O(n²),為什麼還常用?

當每次隨機選 Pivot 時,觸發最壞情況的機率極低,平均表現是 O(n log n),且 cache 效能好,實際執行速度通常優於合併排序。

插入排序何時勝過快速排序?

當資料幾乎有序時,插入排序接近 O(n)。Python 的 Timsort 就在小區段或近似有序時切換到插入排序。

「穩定排序」是什麼意思?

相同值的元素排序後仍保持原本相對順序。冒泡、插入、合併是穩定的;選擇、快速、堆積不穩定。

JavaScript 的 Array.sort() 用的是哪種排序?

V8 引擎(Node.js / Chrome)使用 TimSort,一種結合合併排序與插入排序的混合演算法。它是穩定的,平均時間複雜度 O(n log n),對近乎有序的資料尤其快。

什麼是「原地排序(In-place)」?

排序過程中不需要額外開闢與輸入等比例的記憶體空間,僅使用 O(1) 或 O(log n) 的輔助空間。冒泡、選擇、插入、快速、堆積排序都是原地排序;合併排序則需要 O(n) 額外空間。

合併排序為什麼一定需要 O(n) 額外空間?

合併兩個有序子陣列時,必須同時讀取兩側元素再按順序填回,若直接在原陣列操作會覆蓋還未讀到的值。因此需要暫存左半或整段的副本,最多使用 O(n) 的額外記憶體。

堆積排序和快速排序都是 O(n log n),哪個實際更快?

實務上快速排序通常更快。堆積排序的記憶體存取順序較跳躍(父子節點距離遠),cache 命中率低;快速排序的分區操作是連續存取,cache 效率高。但在最壞情況保證上,堆積排序更可靠。

快速排序 Pivot 的選擇策略有哪些?

常見策略:① 固定選第一或最後一個元素(最簡單,但有序時退化到 O(n²));② 隨機選取(大幅降低最壞情況機率);③ 三數取中(取首、尾、中位數的中間值);④ Median of Medians(可保證最壞 O(n log n),但常數大,較少用)。

各程式語言標準函式庫用的是什麼排序?

Python:TimSort(合併 + 插入)。Java:基本型別用雙 Pivot 快速排序,物件用 TimSort。C++ STL:introsort(快速 + 堆積 + 插入的混合,保證 O(n log n))。Swift / Rust:也採用 TimSort 或類似的混合策略。