**定義**:若待排序序列中存在鍵值相等的元素,排序後它們的**相對順序可能改變**。
例子:排序 [(5, A), (3, B), (5, C)] 按第一欄升序。
穩定排序結果:**[(3, B), (5, A), (5, C)]** (A 在 C 前)。
不穩定排序可能結果:**[(3, B), (5, C), (5, A)]** (C 跑到 A 前)。
| 語言/庫 | 排序演算法 | 穩定性 | 說明 |
|---|---|---|---|
Java Arrays.sort(int[]) | 雙軸快速排序 | **不穩定** | 基本型別無「相對順序」概念,不穩定無影響,速度最快 |
Java Arrays.sort(Object[]) | TimSort (歸併+插入) | **穩定** | 物件排序保證穩定,犧牲少量空間換穩定 |
.NET Array.Sort (基本型別) | 內省排序 | **不穩定** | 同 Java 基本型別 |
.NET List.Sort / OrderBy | TimSort / 快速排序 | **穩定** | .NET Core 3.0+ List.Sort 改為穩定實現 |
Python list.sort | TimSort | **穩定** | 預設穩定 |
C++ std::sort | 內省排序 | **不穩定** | 有 std::stable_sort 可選 |
// 排序前附加原始索引
var indexed = arr.Select((v, i) => new { Value = v, Index = i }).ToArray();
// 比較器:先比 Value,再比 Index
Array.Sort(indexed, (a, b) => {
int c = a.Value.CompareTo(b.Value);
return c != 0 ? c : a.Index.CompareTo(b.Index);
});
// 還原
for (int i = 0; i < arr.Length; i++) arr[i] = indexed[i].Value;
Arrays.sort(Object[])、Collections.sort、Stream.sorted() 皆穩定。List.Sort、Enumerable.OrderBy、Array.Sort (配合 IComparer 但 .NET 6+ 已穩定)。std::stable_sort (歸併排序,O(n log n) 額外空間)。錯誤做法:
// 先按姓名排,再按年齡排 -> 年齡排序若不穩定,姓名順序被破壞
Array.Sort(arr, (a,b) => a.Name.CompareTo(b.Name));
Array.Sort(arr, (a,b) => a.Age.CompareTo(b.Age)); // 危險!
正確做法:
// 單次排序,比較器組合多關鍵字
Array.Sort(arr, (a,b) => {
int c = a.Age.CompareTo(b.Age);
return c != 0 ? c : a.Name.CompareTo(b.Name);
});
Array.Sort/Arrays.sort,最快且無副作用。List.Sort, OrderBy, Collections.sort)。「不穩定」≠「不正確」。快速排序在基本型別、單關鍵字、不需保持相對順序場景下是**最優選擇**。理解資料類型與業務需求,選對 API 才是關鍵。