假設數組 R[1..n],初始 R[1] 自成有序區,無序區為 R[2..n]。第 i-1 趟(i=2..n)將 R[i] 插入有序區 R[1..i-1] 適當位置,使其保持有序。類似整理撲克牌:左手有序,右手摸牌插入。
R[1..i-1] 中查找插入位置 kR[k..i-1] 整體後移一位R[i] 放入 R[k]注意:若 R[i] 關鍵字 ≥ 有序區所有關鍵字,則原位不動。
將待插入記錄暫存,從右向左比較:
tmp = R[i];
for (j = i-1; j >= 1 && R[j] > tmp; j--)
R[j+1] = R[j]; // 後移
R[j+1] = tmp; // 插入
優勢:只需一次掃描,無需額外查找循環。
利用 R[0] 作為哨兵,雙重作用:
R[i]R[j] > tmp 中,若 j=0 時 R[0] 為最小值,自動終止
void InsertSort(int R[], int n) {
for (int i = 2; i <= n; i++) {
R[0] = R[i]; // 哨兵暫存
int j = i - 1;
while (R[j] > R[0]) { // 自動包含 j>=1 檢查
R[j+1] = R[j];
j--;
}
R[j+1] = R[0];
}
}
| 指標 | 最好情況(已有序) | 最壞情況(逆序) | 平均情況 |
|---|---|---|---|
| 比較次數 | n-1 | n(n-1)/2 | ~n²/4 |
| 移動次數 | 0 | n(n-1)/2 | ~n²/4 |
| 時間複雜度 | O(n) | O(n²) | O(n²) |
| 空間複雜度 | O(1) | ||
std::sort 閾值以下改用插入排序)直接插入排序雖非大數據首選,但其簡潔、穩定、適應性強的特性,使其在特定場景和混合排序算法中不可或缺。