快速排序是面試與工程常考核心。本文實現並對比三種 PHP 版本:簡單易懂但空間換時間、單向掃描(Lomuto 分區)、雙向掃描(Hoare 分區),深度剖析最壞情況、空間複雜度與實際基準測試。
function quick_sort_v1(array $array): array {
if (count($array) <= 1) return $array;
$key = $array[0];
$left = $right = [];
for ($i = 1; $i < count($array); $i++) {
if ($array[$i] >= $key) $right[] = $array[$i];
else $left[] = $array[$i];
}
return array_merge(quick_sort_v1($left), [$key], quick_sort_v1($right));
}
function quick_sort_v2(array &$array, int $start, int $end): void {
if ($start >= $end) return;
$mid = $start;
for ($i = $start + 1; $i <= $end; $i++) {
if ($array[$i] < $array[$mid]) {
$mid++;
[$array[$i], $array[$mid]] = [$array[$mid], $array[$i]];
}
}
[$array[$start], $array[$mid]] = [$array[$mid], $array[$start]];
quick_sort_v2($array, $start, $mid - 1);
quick_sort_v2($array, $mid + 1, $end);
}
$mid 指向「小於基準區」尾部,掃描到更小元素時擴展區間並交換。function quick_sort_v3(array &$array, int $start, int $end): void {
if ($end <= $start) return;
$key = $array[$start];
$left = $start;
$right = $end;
while ($left < $right) {
while ($left < $right && $array[$right] > $key) $right--;
$array[$left] = $array[$right]; // 關鍵:右值覆蓋左值(左值已備份在 $key)
while ($left < $right && $array[$left] < $key) $left++;
$array[$right] = $array[$left]; // 左值覆蓋右值
}
$array[$right] = $key; // 基準歸位
quick_sort_v3($array, $start, $right - 1);
quick_sort_v3($array, $right + 1, $end);
}
$key,左位置已「空出」,可安全被右值覆蓋。若右先動,左值未備份會丟失。$array[$right] = $key? 極端情況 [5,2]:$left=0, $right=1,循環結束時 $left=$right=0,若不寫回 $key,陣列變 [2,2] 錯誤。< / > 而非 <= / >=:相等元素不交換,避免全相等陣列退化為 O(n²) 且產生 n 次無意義交換。| 版本 | 耗時(ms) | 記憶體峰值 | 備註 |
|---|---|---|---|
| v1 (函數式) | ~1,850 | ~45 MB | 大量陣列複製 |
| v2 (Lomuto) | ~420 | ~2 MB | 原地交換 |
| v3 (Hoare) | ~310 | ~2 MB | 交換次數最少 |
| PHP 內建 sort() | ~45 | ~2 MB | C 層混合排序(Timsort) |
sort()/usort():C 實現、高度優化、穩定性經實戰驗證。$pivotIdx = mt_rand($start, $end);
[$array[$start], $array[$pivotIdx]] = [$array[$pivotIdx], $array[$start]];
if ($end - $start < 16) { insertion_sort(...); return; }ext/standard/array.c 中的 php_array_sort 實現理解三種分區策略的本質差異,不僅能應付面試,更能在需要自定義排序邏輯(如多鍵排序、外部排序)時做出正確架構決策。