排序演算法是程式設計基礎。本文提供四種經典排序的 C# 實作,並分析時間複雜度、穩定性與適用場景。所有範例採用泛型與 IComparer<T>,支援任意可比較型別。
| 演算法 | 平均時間 | 最壞時間 | 空間 | 穩定 | 備註 |
|---|---|---|---|---|---|
| 冒泡排序 | O(n²) | O(n²) | O(1) | ✅ | 教學用,實務極少用 |
| 選擇排序 | O(n²) | O(n²) | O(1) | ❌ | 交換次數最少 |
| 插入排序 | O(n²) | O(n²) | O(1) | ✅ | 小規模/近乎有序資料極快 |
| 希爾排序 | O(n^1.3~1.5) | O(n²) | O(1) | ❌ | 插入排序改良,間距遞減 |
public interface ISorter
{
void Sort(T[] array, IComparer comparer = null);
}
public static class SortExtensions
{
public static void Sort(this T[] array) where T : IComparable
=> Array.Sort(array); // 內建 Timsort (混合插入+歸併)
}
public class BubbleSorter : ISorter
{
public void Sort(T[] array, IComparer comparer = null)
{
comparer ??= Comparer.Default;
int n = array.Length;
bool swapped;
for (int i = 0; i < n - 1; i++)
{
swapped = false;
for (int j = 0; j < n - 1 - i; j++)
{
if (comparer.Compare(array[j], array[j + 1]) > 0)
{
(array[j], array[j + 1]) = (array[j + 1], array[j]);
swapped = true;
}
}
if (!swapped) break; // 提前結束優化
}
}
}
public class SelectionSorter : ISorter
{
public void Sort(T[] array, IComparer comparer = null)
{
comparer ??= Comparer.Default;
int n = array.Length;
for (int i = 0; i < n - 1; i++)
{
int minIdx = i;
for (int j = i + 1; j < n; j++)
{
if (comparer.Compare(array[j], array[minIdx]) < 0)
minIdx = j;
}
if (minIdx != i)
(array[i], array[minIdx]) = (array[minIdx], array[i]);
}
}
}
public class InsertionSorter : ISorter
{
public void Sort(T[] array, IComparer comparer = null)
{
comparer ??= Comparer.Default;
int n = array.Length;
for (int i = 1; i < n; i++)
{
T key = array[i];
int j = i - 1;
while (j >= 0 && comparer.Compare(array[j], key) > 0)
{
array[j + 1] = array[j];
j--;
}
array[j + 1] = key;
}
}
}
public class ShellSorter : ISorter
{
public void Sort(T[] array, IComparer comparer = null)
{
comparer ??= Comparer.Default;
int n = array.Length;
// Knuth 序列: h = 3*h + 1
int h = 1;
while (h <= n / 3) h = 3 * h + 1;
while (h > 0)
{
// h-排序(插入排序變體)
for (int i = h; i < n; i++)
{
T key = array[i];
int j = i;
while (j >= h && comparer.Compare(array[j - h], key) > 0)
{
array[j] = array[j - h];
j -= h;
}
array[j] = key;
}
h /= 3;
}
}
}
public static class SortBenchmark
{
public static void Run()
{
var algorithms = new (string Name, ISorter Sorter)[]
{
("Bubble", new BubbleSorter()),
("Selection", new SelectionSorter()),
("Insertion", new InsertionSorter()),
("Shell", new ShellSorter()),
("Array.Sort", new BuiltInSorter())
};
int[] sizes = { 100, 1000, 5000 };
var random = new Random(42);
foreach (int size in sizes)
{
Console.WriteLine($"\n=== Array Size: {size} ===");
int[] original = Enumerable.Range(0, size).Select(_ => random.Next(10000)).ToArray();
foreach (var (name, sorter) in algorithms)
{
int[] copy = (int[])original.Clone();
var sw = Stopwatch.StartNew();
sorter.Sort(copy);
sw.Stop();
bool correct = copy.SequenceEqual(original.OrderBy(x => x));
Console.WriteLine($"{name,-12}: {sw.ElapsedMilliseconds,6} ms {(correct ? "✅" : "❌")}");
}
}
}
}
class BuiltInSorter : ISorter
{
public void Sort(T[] array, IComparer comparer = null)
=> Array.Sort(array, comparer ?? Comparer.Default);
}
=== Array Size: 100 ===
Bubble : 0 ms ✅
Selection : 0 ms ✅
Insertion : 0 ms ✅
Shell : 0 ms ✅
Array.Sort : 0 ms ✅
=== Array Size: 1000 ===
Bubble : 12 ms ✅
Selection : 3 ms ✅
Insertion : 1 ms ✅
Shell : 0 ms ✅
Array.Sort : 0 ms ✅
=== Array Size: 5000 ===
Bubble : 285 ms ✅
Selection : 72 ms ✅
Insertion : 18 ms ✅
Shell : 3 ms ✅
Array.Sort : 1 ms ✅
Array.Sort / List.Sort(Timsort,O(n log n)、穩定、高度優化)Array.Sort 內部已平行化(大陣列)理解經典排序演算法有助於面試與演算法思維訓練,但生產代碼請優先使用框架內建排序。若需客製化比較邏輯,實作 IComparer<T> 並傳入 Array.Sort(array, comparer) 即可獲得最佳效能與正確性。