雖然 PHP 內建 sort()、usort() 等高效排序函數,但理解經典排序算法邏輯,對於面試、教學、特殊場景(如自定義比較、教學示範)至關重要。本文以 PHP 實作三大基礎排序,附上逐步執行追蹤與複雜度分析。
重複遍歷陣列,比較相鄰元素,大者後移(升序),每輪將最大值「冒泡」至末尾。
<?php
function bubbleSort(array &$arr): void {
$n = count($arr);
for ($i = 0; $i < $n - 1; $i++) {
$swapped = false;
for ($j = 0; $j < $n - 1 - $i; $j++) {
if ($arr[$j] > $arr[$j + 1]) {
[$arr[$j], $arr[$j + 1]] = [$arr[$j + 1], $arr[$j]]; // PHP 7.1+ 解構賦值
$swapped = true;
}
}
if (!$swapped) break; // 優化:提前結束
}
}
// 測試
$arr = [3, 5, -1, 0, 2];
bubbleSort($arr);
print_r($arr); // [-1, 0, 2, 3, 5]
第1輪外循環:3,5,-1,0,2 → 3,-1,5,0,2 → 3,-1,0,5,2 → 3,-1,0,2,5 (5 就位) 第2輪:3,-1,0,2,5 → -1,3,0,2,5 → -1,0,3,2,5 → -1,0,2,3,5 (3 就位) 第3輪:-1,0,2,3,5 (無交換,提前結束)
每輪從未排序區間選出最小值,與區間首位交換。
<?php
function selectionSort(array &$arr): void {
$n = count($arr);
for ($i = 0; $i < $n - 1; $i++) {
$minIdx = $i;
for ($j = $i + 1; $j < $n; $j++) {
if ($arr[$j] < $arr[$minIdx]) {
$minIdx = $j;
}
}
if ($minIdx !== $i) {
[$arr[$i], $arr[$minIdx]] = [$arr[$minIdx], $arr[$i]];
}
}
}
// 測試
$arr = [2, 1, -1, 3, 0];
selectionSort($arr);
print_r($arr); // [-1, 0, 1, 2, 3]
初始:2,1,-1,3,0 第1輪:找最小值 -1(索引2),與索引0交換 → -1,1,2,3,0 第2輪:剩餘 [1,2,3,0] 最小值 0(索引4),與索引1交換 → -1,0,2,3,1 第3輪:剩餘 [2,3,1] 最小值 1(索引4),與索引2交換 → -1,0,1,3,2 第4輪:剩餘 [3,2] 最小值 2(索引4),與索引3交換 → -1,0,1,2,3
維護有序前綴,將下一元素插入已排序區間適當位置(類似整理撲克牌)。
<?php
function insertionSort(array &$arr): void {
$n = count($arr);
for ($i = 1; $i < $n; $i++) {
$key = $arr[$i];
$j = $i - 1;
while ($j >= 0 && $arr[$j] > $key) {
$arr[$j + 1] = $arr[$j];
$j--;
}
$arr[$j + 1] = $key;
}
}
// 測試
$arr = [2, 1, -1, 3, 0];
insertionSort($arr);
print_r($arr); // [-1, 0, 1, 2, 3]
初始:2,1,-1,3,0 i=1:key=1,比較 2>1 → 2 後移 → 插入 1 於索引0 → 1,2,-1,3,0 i=2:key=-1,比較 2>-1 → 2 後移;1>-1 → 1 後移 → 插入 -1 於索引0 → -1,1,2,3,0 i=3:key=3,比較 2>3 否 → 插入 3 於索引3 → -1,1,2,3,0 i=4:key=0,比較 3>0 → 3 後移;2>0 → 2 後移;1>0 → 1 後移;-1>0 否 → 插入 0 於索引1 → -1,0,1,2,3
| 算法 | 平均時間 | 最佳時間 | 空間 | 穩定 | 適用場景 |
|---|---|---|---|---|---|
| 冒泡 | O(n²) | O(n) | O(1) | 是 | 教學、極小資料、近乎有序 |
| 選擇 | O(n²) | O(n²) | O(1) | 否 | 寫入成本高於讀取、記憶體受限 |
| 插入 | O(n²) | O(n) | O(1) | 是 | 小規模、近乎有序、線上排序 |
sort($arr); // 索引陣列升序
rsort($arr); // 降序
asort($arr); // 關聯陣列保持鍵值升序
uasort($arr, fn($a, $b) => $a <=> $b); // 自定義比較(PHP 7+ 太空船運算子)
uasort/uksort。array_column + array_multisort。掌握經典算法邏輯,能讓你在面對特殊排序需求(如自定義比較器、外部排序、併發排序)時靈活變通,同時深刻理解為何現代語言內建排序採用混合策略。