上一篇,我们讨论了插入排序,而本篇要讨论的希尔排序本质上是由多趟插入排序复合而成的.
因此,看本篇博客之前请先看上一篇的插入排序,这样或许可以为你带来更好的阅读体验
一.例子(一趟排序)
假设我们要对上面这一组数据排序
1.首先我们把这些数据分为gap组,gap也是一组的距离(这里我们假设gap=3),
2.然后对黑颜色的这组,红颜色的这组,绿颜色的这三组分别进行插入排序.
这就是一趟希尔排序的过程
二.过程详解
gap不断缩小(按gap=gap/3+1这种形式缩小),每缩小一次进行一趟插入排序,直到gap=1的时即可排序完成.
希尔排序是由预排序和直接插入排序两部分组成:
1.预排序 gap>1
2.直接插入排序 gap=1
三.代码实现
#include<stdio.h>
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;
for (int i = 0; i < n - gap; ++i)
//注意循环结束条件,当到n-gap时,所有的组已经比较完了
//n-gap之后的数前面已经比较过了
//为什么不是i+=gap,而是i++?
//如果这样的话外面还要加一层gap的for循环,显然这样算法的效率是很低的
//直接i++,这样省去了一层for循环,一个数接一个数比
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
}
void PrintArray(int* a, int n)
{
for (int i = 0; i < n; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
}
void TestShellSort()
{
int a[] = { 9,1,2,5,7,4,8,6,3,6 };
ShellSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}
int main()
{
TestShellSort();
return 0;
}
1.注意循环结束条件,为什么是n-gap
当到n-gap时,所有的组已经比较完了
n-gap之后的数前面已经比较过了
2.为什么for循环里面不是i+=gap,而是i++?
如果这样的话外面还要加一层gap的for循环,显然这样算法的效率是很低的
直接i++,这样省去了一层for循环,一个数接一个数比
四.注意事项
1.希尔排序实际上是多次插入排序
2.希尔排序分为两个过程,预排序(gap>1)和插入排序(gap=1)
3.希尔排序实际上是一种增量(gap)不断缩小的过程