🌟hello,各位读者大大们你们好呀🌟
🍭🍭系列专栏:【数据结构初阶】
✒️✒️本篇内容:深入剖析希尔排序
🚢🚢作者简介:计算机海洋的新进船长一枚,请多多指教( •̀֊•́ ) ̖́-
📡📡同期数据结构文章:【数据结构初阶】C语言从0到1带你了解直接插入排序
需要直接插入排序的基础,才能更好的理解文章,详情可见上栏同期数据结构文章
先选定一个整数,把待排序文件中所有数分成 gap 个组,所有距离为 gap 的数分在同一组内,并对每一组内的数先进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
1.先进行预排序,将一组数分为 gap 组,对间隔为 gap 的数进行直接插入排序

- void ShellSort(int* a, int n)
- {
- int gap;
- int end;
- int tmp = a[end + gap];
- while (end >= 0)
- {
- if (a[end] > tmp)
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
-
- a[end + gap] = tmp;
- }
至此,我们已经完成了一次插入排序,也就是可以将红色组的9、5变得有序。接下来就是加入循环,完成多次插入排序,使间隔为 gap 的数组成的数组有序,以下图红色组为例,就是将 9,5,8,5 变得有序

2.加入循环,完成多次插入排序,使间隔为 gap 的数组成的数组有序
- int gap = 3;
- for (int i = 0; i < n - gap; i += gap)
- {
- // [0,end] 插入 end+gap [0, end+gap]有序 -- 间隔为gap的数据
- int end = i;
- int tmp = a[end + gap];
- while (end >= 0)
- {
- if (a[end] > tmp)
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
- a[end + gap] = tmp;
- }
至此,我们第一组(红色组)就排完了,数组将会变成 5,1,2,5,7,4,8,6,3,9
3.再加一组循环,循环 gap 次,使 gap 组的数都变得有序(以下数组为例,就是让红、蓝、绿组都变得有序)

- void ShellSort(int* a, int n)
- {
- int gap = 3;
- for (int j = 0; j < gap; ++j)
- {
- for (int i = j; i < n - gap; i += gap)
- {
- // [0,end] 插入 end+gap [0, end+gap]有序 -- 间隔为gap的数据
- int end = i;
- int tmp = a[end + gap];
- while (end >= 0)
- {
- if (a[end] > tmp)
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
- a[end + gap] = tmp;
- }
- }
4.算法优化,三层循环变两层循环(时间复杂度相同,所以写上面的这种也行)

- void ShellSort(int* a, int n)
- {
- int gap = 3;
- for (int i = j; i < n - gap; ++i)
- {
- // [0,end] 插入 end+gap [0, end+gap]有序 -- 间隔为gap的数据
- int end = i;
- int tmp = a[end + gap];
- while (end >= 0)
- {
- if (a[end] > tmp)
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
- a[end + gap] = tmp;
- }
- }
至此,我们已经完成了预排序, 完成了数组接近有序的目标,大大降低了对每个数直接排序的时间复杂度
5.对每个数进行直接插入排序,我们可以通过控制 gap 的值,来区分预排序和直接插入排序
- // gap > 1 预排序
- // gap == 1 直接插入排序
-
- // O(N^1.3)
- void ShellSort(int* a, int n)
- {
- int gap = n;
- while (gap > 1)
- {
- //gap = gap / 2;
- gap = gap / 3 + 1; //+1是为了保证除到最后的数=1
-
- // [0,end] 插入 end+gap [0, end+gap]有序 -- 间隔为gap的数据
- for (int i = 0; i < n - gap; ++i)
- {
- int end = i;
- int tmp = a[end + gap];
- while (end >= 0)
- {
- if (a[end] > tmp)
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
- a[end + gap] = tmp;
- }
- }
- }
6.我们将上述代码补充完整,进行一次实验
sort.h
- #include
- #include
-
- void ShellSort(int* a, int n);
sort.c
- void PrintArray(int* a, int n)
- {
- for (int i = 0; i < n; ++i)
- {
- printf("%d ", a[i]);
- }
- printf("\n");
- }
-
- // gap > 1 预排序
- // gap == 1 直接插入排序
-
- // O(N^1.3)
- void ShellSort(int* a, int n)
- {
- int gap = n;
- while (gap > 1)
- {
- //gap = gap / 2;
- gap = gap / 3 + 1; //+1是为了保证除到最后的数=1
-
- // [0,end] 插入 end+gap [0, end+gap]有序 -- 间隔为gap的数据
- for (int i = 0; i < n - gap; ++i)
- {
- int end = i;
- int tmp = a[end + gap];
- while (end >= 0)
- {
- if (a[end] > tmp)
- {
- a[end + gap] = a[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
- a[end + gap] = tmp;
- }
- }
- }
test.c
- void TestShellSort()
- {
- //int a[] = { 9,8,7,6,5,4,3,2,1,0 };
- int a[] = { 34, 56, 25, 65, 86, 99, 72, 66 };
- ShellSort(a, sizeof(a) / sizeof(int));
- PrintArray(a, sizeof(a) / sizeof(int));
- }
-
-
- int main()
- {
- TestShellSort();
- return 0;
- }
结果如下

《数据结构-用面相对象方法与C++描述》--- 殷人昆

🌹🌹希尔排序排序大概就讲到这里啦,博主后续会继续更新更多数据结构的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪