希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
9 4 5 7 6 1 3 2 //位置1
选取 步长为4 分为四组
9-6 4-1 5-3 7-2
交换大小后
6-9 1-4 3-5 2-7 放回原位置
6 1 3 2 9 4 5 7
选取步长为2
6 - 3 1 - 2 9 - 5 4 - 7
3 - 6 1 - 2 5 - 9 7 - 4
3 1 5 7 6 2 9 4
3-5 1-7
6-9 2-4 都是有序的
对于这两组 分别进行排序
1 3 5 7
2 4 6 9
选取步长为1
进行直接插入排序
得到:
1 2 3 4 5 6 7 9(有序数组)
希尔排序,也是插入排序的一种,也是对直接插入排序的优化。
也可以叫做 分组插入排序、缩小增量排序。
希尔排序时间复杂度
希尔排序的时间复杂度与增量(即,步长gap)的选取有关。例如,当增量为1时,希尔排序退化成了直接插入排序,此时的时间复杂度为O(N²),而Hibbard增量的希尔排序的时间复杂度为O(N3/2)。
希尔排序稳定性
希尔排序是不稳定的算法,它满足稳定算法的定义。对于相同的两个数,可能由于分在不同的组中而导致它们的顺序发生变化。
算法稳定性 – 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!
void shell_sort1(int a[], int n)
{
int i,j,gap;
// gap为步长,每次减为原来的一半。
for (gap = n / 2; gap > 0; gap /= 2)
{
// 共gap个组,对每一组都执行直接插入排序
for (i = 0 ;i < gap; i++)
{
for (j = i + gap; j < n; j += gap)
{
// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
if (a[j] < a[j - gap])
{
int tmp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > tmp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = tmp;
}
}
}
}
}