希尔排序,或称为缩小增量排序。它通过多次直接插入排序来提高算法的效率,时间复杂度约为O(),空间复杂度为o(1)。
下面是进行升序排序的完整示例:
增量用数组dk来表示,依次通过增量5,3,1对数据进行直接插入排序,3次之后原数据便排好序了。其中insertSort函数是对直接插入排序算法的简单修改,供shellSort函数进行调用,整体结构一目了然。关于增量如何取值可以自行百度。
希尔排序是不稳定的,这与所取的增量有关。如 1,3,3,2四个数,取增量为2,排完序之后为1,2,3,3。再取增量为1,排序结果为1,2,3,3。所以希尔排序是不稳定的。
#include<iostream>
void insertSort(int* arr, int num,int d);
void shellSort(int* arr, int num,int* dk,int n);//希尔排序
int main()
{
int a[20] = { 3, 2, 4, 6, 7, 5, 18, 9, 0, 1,
16, 8, 20, 33, 28, 64, 19, 31, 30, 25 };
for (int i = 0; i < 20; i++)
{
std::cout << a[i] << " ";
}
std::cout << '\n';
int dk[3] = { 5, 3, 1 };//增量依次取5,3,1。
shellSort(a, 20,dk,3);//进行希尔排序
for (int i = 0; i < 20; i++)
{
std::cout << a[i] << " ";
}
return 0;
}
void shellSort(int* arr, int num, int* dk,int n)
{
for (int i = 0; i < n; i++)
insertSort(arr, num, dk[i]);
}
void insertSort(int* arr, int num, int d)
{
int temp, i, j;//temp保存每一次的新数,因为数组元素的移动会覆盖掉新数
for (i = d; i < num; ++i)//所谓外循环,每次放一个新数进去参与排序
{
if (arr[i] < arr[i - d])//若下标i以前的数不是有序的,执行if语句内容
//此时的无序指的是下标0~i-1是有序的,需要将下标i中的数重新插入,使其变得有序
{
temp = arr[i];//保存每次的新数
for (j = i - d; arr[j] > temp&&j >= 0; j-=d)
arr[j + d] = arr[j];
arr[j + d] = temp;
}
}
}