早期教學多示範 int[] 排序,實務上需對 Car、Order、User 等類別按不同欄位 (價格、名稱、日期) 排序。透過 Comparison<T> 或 IComparer<T> 即可解耦演算法與比較邏輯。
public class Car
{
public string Name { get; set; }
public decimal Price { get; set; }
public Car(string name, decimal price) { Name = name; Price = price; }
public override string ToString() => $"{Name} : {Price:C}";
}
public static class SortAlgorithms
{
// 冒泡排序 - 教學用,實務極少用
public static void BubbleSort(T[] array, Comparison cmp)
{
for (int i = 1; i < array.Length; i++)
{
bool swapped = false;
for (int j = array.Length - 1; j >= i; j--)
if (cmp(array[j], array[j - 1]) < 0)
{ (array[j], array[j - 1]) = (array[j - 1], array[j]); swapped = true; }
if (!swapped) break;
}
}
// 快速排序 - 平均 O(n log n),不穩定
public static void QuickSort(T[] array, Comparison cmp) => QuickSort(array, cmp, 0, array.Length - 1);
private static void QuickSort(T[] array, Comparison cmp, int left, int right)
{
if (left >= right) return;
T pivot = array[(left + right) / 2];
int i = left - 1, j = right + 1;
while (true)
{
while (cmp(array[++i], pivot) < 0) ;
while (cmp(pivot, array[--j]) < 0) ;
if (i >= j) break;
(array[i], array[j]) = (array[j], array[i]);
}
QuickSort(array, cmp, left, i - 1);
QuickSort(array, cmp, j + 1, right);
}
// 選擇排序 - O(n²),不穩定,寫入次數少 (適合寫入成本高的存儲)
public static void SelectionSort(T[] array, Comparison cmp)
{
for (int i = 0; i < array.Length - 1; i++)
{
int min = i;
for (int j = i + 1; j < array.Length; j++)
if (cmp(array[j], array[min]) < 0) min = j;
(array[i], array[min]) = (array[min], array[i]);
}
}
// 插入排序 - O(n²),穩定,近乎有序資料極快 (最佳 O(n))
public static void InsertionSort(T[] array, Comparison cmp)
{
for (int i = 1; i < array.Length; i++)
{
T key = array[i];
int j = i;
while (j > 0 && cmp(key, array[j - 1]) < 0)
{ array[j] = array[j - 1]; j--; }
array[j] = key;
}
}
}
public static class CarComparers
{
public static Comparison ByPriceAsc => (a, b) => a.Price.CompareTo(b.Price);
public static Comparison ByPriceDesc => (a, b) => b.Price.CompareTo(a.Price);
public static Comparison ByNameAsc => (a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal);
public static Comparison ByNameDesc => (a, b) => string.Compare(b.Name, a.Name, StringComparison.Ordinal);
// 多鍵排序:先價格升冪,價格相同再按名稱
public static Comparison ByPriceThenName => (a, b) =>
{
int r = a.Price.CompareTo(b.Price);
return r != 0 ? r : string.Compare(a.Name, b.Name, StringComparison.Ordinal);
};
}
var cars = new[]
{
new Car("Benz", 210000), new Car("BMW", 150000), new Car("VW", 130000),
new Car("Ford", 140000), new Car("Kia", 58000), new Car("QQ", 30000),
new Car("Fiat", 200000), new Car("Toyota", 170000), new Car("Mazda", 140000)
};
// 快速排序 + 價格升冪
SortAlgorithms.QuickSort(cars, CarComparers.ByPriceAsc);
Console.WriteLine("價格升冪:");
cars.ToList().ForEach(c => Console.WriteLine(c));
// 插入排序 + 多鍵排序
SortAlgorithms.InsertionSort(cars, CarComparers.ByPriceThenName);
Console.WriteLine("\n價格升冪、同價按名稱:");
cars.ToList().ForEach(c => Console.WriteLine(c));
// List.Sort / Array.Sort / LINQ OrderBy 已高度優化 (Introsort: Quick + Heap + Insertion)
cars = cars.OrderBy(c => c.Price).ThenBy(c => c.Name).ToArray();
// 或
Array.Sort(cars, CarComparers.ByPriceThenName);
| 方法 | 優點 | 適用場景 |
|---|---|---|
Array.Sort / List.Sort | 原地排序、Introsort 保證 O(n log n)、支援 Comparison<T> | 一般陣列/清單排序首選 |
LINQ OrderBy | 語法宣告式、可鏈結 ThenBy、回傳新序列 | 查詢管線、需保留原序列 |
| 自訂演算法 | 教學、特殊限制 (外部排序、穩定性保證、寫入最小化) | 極少數特殊場景 |
掌握 Comparison<T> 與 IComparer<T> 介面,即可將任何排序演算法泛型化,支援任意型別與複雜多欄位排序規則。實務開發中優先使用 .NET 內建 Array.Sort / List.Sort / LINQ OrderBy,僅在教學、面試或極特殊效能限制下手寫演算法。