算法思想
- 根据直接插入排序的特点,当数组中的值越有序,速度也就越快,所以希尔排序实际上是根据这一思想,每次将数组分成几组,对每组进行直接插入排序,每组的数据会越来越有序,整体的数组中的值也就会越来越有序
- 将数组的元素按一定的规律分组,可以降低时间复杂度,比如可以先分为五组,每组排序好之后,再分为三组,每组排序好之后,再分为1组。最后一次一定要分为一组,才可以将全部数据都排好序
举例说明
相同背景颜色的为一组
原始数据 | 78,62,6,90,34,9,23,67,98,45,53,27,71,16,87 |
分成五组 | 78,62,6,90,34,9,23,67,98,45,53,27,71,16,87 |
每组排完序 | 9,23,6,16,34,53,27,67,90,45,78,62,71,98,87 |
分成三组 | 9,23,6,16,34,53,27,67,90,45,78,62,71,98,87 |
每组排完序 | 9,23,6,16,34,53,27,67,62,45,78,87,71,98,90 |
分成一组 | 9,23,6,16,34,53,27,67,62,45,78,87,71,98,90 |
每组排完序 | 6,9,16,23,27,34,45,53,62,67,71,78,87,90,98 |
代码实现
void Shell(int* ar, int len, int gap)//此处实际上为直接插入排序的算法
{
for (int i = gap; i < len; i += gap)
{
int tmp = ar[i];
int j = i - gap;
for (; j >= 0; j -= gap)
{
if (ar[j] > tmp)
{
ar[j + gap] = ar[j];
}
else
{
break;
}
}
ar[j + gap] = tmp;
}
}
void ShellSort(int* ar, int len)
{
assert(ar != nullptr);
int gap[3] = { 5,3,1 };
int count = sizeof(gap) / sizeof(gap[0]);
for (int i = 0; i < count; ++i)
{
Shell(ar, len, gap[i]);
}
}
void My_print(int* ar, int len)
{
for (int i = 0; i < len; ++i)
{
printf("%3d", ar[i]);
}
printf("\n");
}
int main()
{
int ar[] = { 78,62,6,90,34,9,23,67,98,45,53,27,71,16,87 };
int len = sizeof(ar) / sizeof(ar[0]);
ShellSort(ar, len);
My_print(ar, len);
return 0;
}
代码分析
- 时间复杂度:希尔排序的时间复杂度比较特殊,为O()~O()
- 空间复杂度:O(1)
- 稳定性:不稳定,因为有跳跃交换