算法思路
希尔排序的基本思想是:先将待排序的数组按照一定的步长进行分组,然后对每组中的元素进行插入排序。
随着步长逐渐减小,每组包含的元素越来越少,当步长减小到1时,整个数组被分成了一组,排序完成。
在函数内部,我们首先计算出数组的长度 n,并初始化步长 gap 为 n 的一半。然后进行循环:
- 对于每个 gap,将数组分成多个子序列,对每个子序列进行插入排序。
- 插入排序是将待排序的元素插入到有序的数组中,从而扩大有序数组的范围。
- 在插入排序中,我们使用了一个临时变量 temp 来存储当前元素的值,然后将其依次与前面的元素进行比较,如果前面的元素比它大,则将前面的元素向后移动一个位置,直到找到比它小的位置。
- 最后,将当前元素插入到找到的位置之后。
最后,我们将步长除以2,并继续循环,直到步长为1时,排序完成。
动画演示
代码实现
#include <iostream>
#include <vector>
using namespace std;
void shell_sort(vector<int>& arr) {
int n = arr.size();
// 初始步长为数组长度的一半,然后每次除以2
for (int gap = n / 2; gap > 0; gap /= 2) {
// 插入排序
for (int i = gap; i < n; i++) {
int temp = arr[i];
int j;
for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
arr[j + gap] = arr[j];
}
arr[j + gap] = temp;
}
}
}
int main() {
vector<int> arr = {6, 8, 3, 2, 9, 1, 4, 7, 5};
shell_sort(arr);
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
输出结果
1 2 3 4 5 6 7 8 9
希尔排序的时间复杂度是取决于增量序列的,最坏时间复杂度是 O(n^2),平均时间复杂度介于 O(n log n) 和 O(n^2) 之间。