希尔排序
版本1
话不多说,先上代码
易懂版:
注:两个版本是等效的
void ShellSort(int* a, int n)
{
int gap = n / 2;
while (gap)
{
for (int j = 0; j < gap; j++)
{
for (int i = j + gap; i < n; i += gap)
{
int end = i;
while (end > j)
{
if (a[end] < a[end - gap])
{
Swap(&a[end], &a[end - gap]);
--end;
}
else break;
}
}
}
gap/=2;
}
}
希尔排序是插入排序的改进版,核心思想是:
1. 第一步,将原数组分为n组,每组有gap个数,所以每组的第一个也就间隔gap个位置。然后,将每组进行插入排序,使整个数组相对有序化。称为预排序,这也是精髓。
2. 第二步,缩小gap值,多次进行组内插排。最后将gap设为1,即总体进行插入排序,则全体有序。
版本2
版本二
void ShellSort(int* a, int n)//O(N)约N^1.3
{
int gap = n;//gap较大时,可尽快将大数挪至后方;gap较小时,可更接近有序;gap=1时,即为插排
while (gap > 1)
{
gap = gap / 3 + 1;
for (int i = 0; i < n - gap; i++)//此处两层循环由于i++,等价于三层循环,把所有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;
}
}
}
上面这个版本自己领悟,注重领悟第二层循环处i++的妙处。
时间复杂度
关于时间复杂度,可以认为约等于N的1.3次方。属于是排序里的王者级别大佬。
O(N)的计算相当复杂,(貌似因为每一次预排序都对后面排序的所需时间产生影响)
上链接!自己参透吧哈哈
Wiki关于希尔时间复杂度的分析