經典歸併排序對**逆序數據**性能退化至 O(n²)。TimSort(Python/Java/Android 默認排序算法)針對**真實世界數據常含有序片段**的特點,通過**自然分區**與**智能歸併策略**實現:
O(n)O(n log n)O(n)MIN_MERGE = 32。分區過小時用二分插入排序擴充至 minRun(根據數組長度計算,2的冪附近)。runLen[i-3] > runLen[i-2] + runLen[i-1] (1) runLen[i-2] > runLen[i-1] (2)違反時觸發合併:優先合併較小的相鄰分區,避免大分區重複參與合併(類似 Huffman 編碼思想)。
new Object[n/2],歸併時交換角色,減少 GC 壓力。TimSort.sort()// 計算 minRun
int minRun = minRunLength(nRemaining);
do {
// 1. 獲取下一個 run(含反轉遞減 run)
int runLen = countRunAndMakeAscending(a, lo, hi);
// 2. 過短 run 用二分插入排序擴充
if (runLen < minRun) {
int force = Math.min(minRun, nRemaining);
binarySort(a, lo, lo + force, lo + runLen);
runLen = force;
}
// 3. 壓入棧
ts.pushRun(lo, runLen);
// 4. 檢查不變量,必要時合併
ts.mergeCollapse();
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);
// 5. 強制合併剩餘所有 run
ts.mergeForceCollapse();
mergeCollapse()private void mergeCollapse() {
while (stackSize > 1) {
int n = stackSize - 2;
if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
if (runLen[n-1] < runLen[n+1]) n--; // 合併較小的那對
mergeAt(n);
} else if (runLen[n] <= runLen[n+1]) {
mergeAt(n);
} else {
break; // 滿足不變量
}
}
}
mergeLo/mergeHigallop 模式)。MIN_GALLOP = 7 次命中切換到膽怯模式,否則回退普通逐個比較。| 數據類型 | Arrays.sort (TimSort) | 快速排序 | 歸併排序 |
|---|---|---|---|
| 隨機數據 | 基準 | 略快 | 較慢 |
| 近乎有序 | 極快 (O(n)) | 退化 | 快 |
| 逆序 | 快 (O(n log n)) | 退化 O(n²) | 退化 O(n²) |
| 大量重複鍵 | 穩定、快 | 需三向切分 | 穩定、快 |
IllegalArgumentException: Comparison method violates its general contract。