將陣列分為「已排序區」與「未排序區」。初始已排序區僅含首元素。每輪從未排序區取出首元素 key,在已排序區從右向左掃描,將大於 key 的元素右移,騰出位置插入 key。類似撲克牌整理手牌。


void InsertSort(int *A, int n) {
int i, j, key;
for (i = 1; i < n; i++) {
key = A[i];
for (j = i; j > 0 && key < A[j-1]; j--) {
A[j] = A[j-1]; // 右移
}
A[j] = key;
}
}
| 情況 | 比較次數 | 移動次數 | 總體 |
|---|---|---|---|
| 最好(已有序) | N-1 | 0 | O(N) |
| 最壞(逆序) | N(N-1)/2 | N(N-1)/2 | O(N²) |
| 平均 | ~N²/4 | ~N²/4 | O(N²) |
i < j 且 A[i] > A[j]。N(N-1)/4。(x,y) 必在 A 或 A' 中構成逆序對。總對數 C(N,2)=N(N-1)/2,故 A 平均逆序對 = 一半 = N(N-1)/4。插入排序只比較相鄰元素,移動代價大。希爾排序引入增量序列 h₁, h₂, ..., hₖ=1,每輪按增量 h 分組進行插入排序,使元素大步長移動,最後一輪 h=1 即普通插入排序,但此時陣列已近乎有序,極快。
| 增量序列 | 公式 | 時間複雜度 | 備註 |
|---|---|---|---|
| Shell 原始 | N/2, N/4, ..., 1 | O(N²) | 最差,不推薦 |
| Hibbard | 2ᵏ-1: 1, 3, 7, 15... | O(N3/2) | 較好 |
| Sedgewick | 1, 5, 19, 41, 109... | O(N4/3) 或 O(N7/6) | 目前最佳實用序列 |
| Pratt | 2ᵖ3ᑫ | O(N log²N) | 常數大,工程少用 |
void ShellSort(int *A, int n) {
int i, j, inc, key;
for (inc = n/2; inc > 0; inc /= 2) {
for (i = inc; i < n; i++) {
key = A[i];
for (j = i; j >= inc && key < A[j-inc]; j -= inc) {
A[j] = A[j-inc];
}
A[j] = key;
}
}
}
h-排序後,陣列滿足 A[i] <= A[i+h],稱為 h-有序。h-有序性。| 維度 | 插入排序 | 希爾排序 |
|---|---|---|
| 最好時間 | O(N) | O(N log N) 或 O(N1.5) |
| 最壞時間 | O(N²) | O(N²) (Shell) / O(N1.5) (Hibbard) |
| 平均時間 | O(N²) | O(N1.25~1.5) |
| 空間 | O(1) | O(1) |
| 穩定性 | 穩定 | 不穩定 |
| 工程應用 | 小陣列、近乎有序 | 中等規模、嵌入式系統、庫函數備選 |