快速排序是經典的分治法應用,平均時間複雜度 O(n log n),原地排序、空間複雜度 O(log n)(遞迴堆疊)。基本流程三步驟:
using System;
namespace QuickSortDemo
{
///
/// 快速排序工具類別
///
public class QuickSort
{
///
/// 公開進入點:排序整個陣列或指定區間
///
public void Sort(int[] list, int low, int high)
{
if (high <= low) return; // 0 或 1 個元素
if (high == low + 1) // 2 個元素直接比較交換
{
if (list[low] > list[high]) Swap(ref list[low], ref list[high]);
return;
}
InternalQuickSort(list, low, high); // 3+ 元素進入正式快排
}
///
/// 遞迴核心
///
private void InternalQuickSort(int[] list, int low, int high)
{
if (low < high)
{
int pivot = Partition(list, low, high);
InternalQuickSort(list, low, pivot - 1);
InternalQuickSort(list, pivot + 1, high);
}
}
///
/// 分區:採雙向掃描法,回傳基準值最終位置
///
private int Partition(int[] list, int low, int high)
{
int pivot = list[low]; // 取首元素為基準
while (low < high)
{
// 從右向左找第一個 < pivot
while (low < high && list[high] >= pivot) high--;
if (low != high) Swap(ref list[low++], ref list[high]);
// 從左向右找第一個 > pivot
while (low < high && list[low] <= pivot) low++;
if (low != high) Swap(ref list[low], ref list[high--]);
}
return low; // low == high 即為基準值位置
}
///
/// 交換兩個整數
///
private void Swap(ref int a, ref int b)
{
int t = a; a = b; b = t;
}
}
// 測試用例
class Program
{
static void Main()
{
int[] data = { 5, 2, 9, 1, 5, 6, 3, 8, 7, 4 };
Console.WriteLine("排序前:" + string.Join(", ", data));
new QuickSort().Sort(data, 0, data.Length - 1);
Console.WriteLine("排序後:" + string.Join(", ", data));
}
}
}
O(n²)。Partition 同時從左右逼近,減少交換次數,優於單向 Lomuto 分區法。void Sort<T>(T[] array, int low, int high) where T : IComparable<T> 支援任意可比較型別。| 優點 | 缺點 |
|---|---|
| 平均速度最快的通用排序 | 最壞情況 O(n²)(可透過隨機基準緩解) |
| 原地排序,記憶體額外開銷極小 | 不穩定排序(相等元素相對位置可能改變) |
| 快取局部性好,實際執行常勝過 MergeSort | 遞迴深度極端情況可能堆疊溢位(可改迭代實作) |
快速排序是演算法面試與實務開發的必修課。理解其分區邏輯、遞迴終止條件與基準值選取策略,能靈活應對各種排序需求。生產環境建議直接使用 Array.Sort / List<T>.Sort(內建 IntroSort:快排+堆排+插排混合),唯有教學、特殊約束或嵌入式環境才需自行實作。