排序視覺化最容易看錯的,不是動畫漂不漂亮,而是兩個值一樣時,誰可以搶到前面。穩定排序要求:鍵值相同的元素,排完後仍保持輸入時的相對順序。不穩定排序允許它們對調。這個差別在學作業裡常被當選擇題,在真實資料裡則出現在「先依分數排、再依姓名排」這種多鍵排序。本文對準怎麼用動畫讀穩定與複雜度,不把六種演算法逐步偽代碼重抄一遍。
穩定到底在保護什麼
假設名單是 (5, 甲)、(5, 乙)、(3, 丙),只依數字排。穩定的結果必須是甲仍在乙前面,因為兩人分數相同、輸入時甲較早。不穩定的演算法可能變成乙在甲前面,數字上看都排對了,次要資訊卻丟了。
為什麼有人在乎:你先用穩定排序依「班級」排,再用穩定排序依「成績」排,成績相同的人仍會留在原班級相對位置。若第二趟用不穩定排序,班級這個次要鍵可能被打亂,看起來像程式寫錯。
姓名筆畫排序爭的是漢字怎麼數;這裡爭的是相同鍵不要被演算法偷偷交換。兩者都是「順序一旦被定義,就不要無聲改寫」。
視覺化時,建議把兩個相同高度的柱子當成甲與乙:看交換發生時,相同高度有沒有對調。若動畫只著色「正在比較/正在交換」,沒有標出相同鍵,就很難看出穩定性,這時要靠定義而不是靠感覺。
六種常見演算法,先記穩定性再記大 O
線上視覺化常見這幾種(與多數教材一致):
- 冒泡、插入、合併:穩定。交換或搬移時,不會無故讓相同鍵越過彼此。
- 選擇、快速、堆積:通常不穩定。選擇會把最小值一路換到前面,可能跨過相同鍵;快速排序的分割也常把相等元素分到樞紐兩側而不保留原順序。
時間複雜度是另一條軸,不要和穩定混成一句話:
- 冒泡、選擇、插入:平均約 O(n2)。n 變大時,比較與交換次數成長很快。
- 快速:平均約 O(n log n),最壞可到 O(n2),例如資料已經有序且樞紐總選到極端值。
- 合併、堆積:平均與最壞都可維持 O(n log n)。合併需要額外約 O(n) 空間;堆積可較省空間,但不穩定。
大 O 描述的是成長趨勢,不是「n=1000 就一定跑 100 萬次」的精準計數。視覺化用幾十根柱子,O(n2) 與 O(n log n) 的差距還不明顯;把 n 想到上千、上萬,差異才變成作業與系統裡真正痛的地方。
插入排序有一個實務例外:資料幾乎已經有序時,它往往接近線性,常數也小。這也是許多語言標準函式庫在小區段或近乎有序時,會摻進插入排序的原因。實際用了哪一種混合策略,以該語言當前文件為準,不要把某一版引擎實作當成永恆標準。
看動畫時建議盯的三件事
- 比較對:兩根柱子亮起來,代表正在問誰較大,還不一定交換。
- 交換或搬移:位置真的改了。穩定與否,發生在這一步。
- 已定位區間:冒泡常把最大值沉到右端;快速排序會出現樞紐左邊都較小、右邊都較大的分界。看懂「這一區以後不會再動」,比看完整首歌式的閃爍有用。
快速排序最壞退化時,視覺上會變成一直切出很歪的兩邊,遞迴層數變深,柱子幾乎沒在減半。這時對照「為什麼還有人用快速排序」:平均情況切得夠均勻、記憶體存取也較連續,實務上常常仍很快;但若你需要最壞情況也保證 O(n log n),合併或堆積比較好講清楚。
合併排序的代價是額外陣列。動畫若顯示左右兩段再寫回,那就是空間換時間與穩定性。分帳要減少轉帳次數,想的是另一種組合壓縮;排序穩定則是在許可的交換集合裡,拒絕打亂相同鍵。都是「正確結果可以有很多,選哪一種副作用」。
選演算法時的短清單
- 只要數字對、不在乎相同鍵:多數情況快速排序或標準函式庫就夠。
- 必須保留相同鍵原順序、或要做多鍵排序:選穩定者,合併或插入較直覺。
- 記憶體很緊、又要最壞 O(n log n):堆積是教材上的常客,但實務常數與快取行為未必贏快速。
- n 很小或幾乎有序:先懷疑插入,不要無腦上分治。
- 作業要你「手寫並分析」:用視覺化對照比較次數與交換次數,比只背表格不容易寫反。
把表格資料轉成 JSON 之後再排序,穩定與否會影響同一分數的列誰先出現。鍵值設計與排序選擇要一起想,而不是先亂排再怪匯出。
結語
穩定排序保護的是相同鍵的輸入順序,時間複雜度保護的是 n 變大以後還能不能等得完。看視覺化時,先認比較與交換,再問相同高度有沒有被換位,最後才把大 O 對回這次資料規不規則。表格能背,動畫能對,作業裡的「為什麼選這個」才寫得出理由。