目录
希尔排序的前世今生
核心思想
代码
动图示例
全部代码
希尔排序是D.L.Shell于1959年提出来的一种排序算法,在这之前排序算法的时间复杂度基本上都是O (N^2),希尔排序是突破这个时间复杂度的第一批算法之一。
插入排序的效率在基本有序的情况下其实是很高的。
希尔排序的思想就是在进行插入排序之前使数据基本有序。
所谓的基本有序,就是小的数据基本在前面,大的数据基本在后面,不大不小的基本在中间。
将某个增量的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。
定义一个增量gap,使得每隔gap个间距的数为一个子序列。先对子序列进行预排序。
当子序列基本有序后,最后一次就是增量为1的间距,就相当于是插入排序。
//希尔排序 时间复杂度 O(N^1.3 ~ N^2)
void ShellSort(int* a, int n)
{
//1.gap>1相当于预排序,让数组接近有序
//2.gap==1相当于直接插入排序,保证有序
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;//保证了gap最后一次一定是1
//gap==1 就相当于插入排序
for (int i = 0; i < n - gap; i++)
{
//多组并排,假设gap=3
//i=0时,i+3=3,子序列下标为:0 3 6 9 ......
//i=1,i+3=4,子序列下标为: 1 4 7 ......
//i=2,i+3=5,子序列下标为:2 5 8 ......
int end = i;
int temp = a[end + gap];//使增量所在位置变为子序列
while (end >= 0)
{
if (temp < a[end])
{
a[end + gap] = a[end];//小就把前一个数向后移动gap个位置
end -= gap;//让下标回到之前的位置
}
else
{
break;//大于或者相等就跳出来
}
}
//end==0,或跳出循环就把值放在gap的位置
a[end + gap] = temp;
}
Printary(a, n);//打印出来看看
}
}
排序结果
#include
#include
//打印函数
void Printary(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
//希尔排序 时间复杂度 O(N^1.3 ~ N^2)
void ShellSort(int* a, int n)
{
//1.gap>1相当于预排序,让数组接近有序
//2.gap==1相当于直接插入排序,保证有序
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;//保证了gap最后一次一定是1
//gap==1 就相当于插入排序
for (int i = 0; i < n - gap; i++)
{
//多组并排,假设gap=3
//i=0时,i+3=3,子序列下标为:0 3 6 9 ......
//i=1,i+3=4,子序列下标为: 1 4 7 ......
//i=2,i+3=5,子序列下标为:2 5 8 ......
int end = i;
int temp = a[end + gap];//使增量所在位置变为子序列
while (end >= 0)
{
if (temp < a[end])
{
a[end + gap] = a[end];//小就把前一个数向后移动gap个位置
end -= gap;//让下标回到之前的位置
}
else
{
break;//大于或者相等就跳出来
}
}
//end==0,或跳出循环就把值放在gap的位置
a[end + gap] = temp;
}
Printary(a, n);//打印出来看看
}
}
void TestShellSort()//希尔
{
int a[] = { 8,9,1,7,2,3,5,4,6,0 };
ShellSort(a, sizeof(a) / sizeof(a[0]));
}
int main()
{
TestShellSort();//直接调用
return 0;
}