希尔排序
将原本大量记录数的记录进行分组。分割成若干个子序列,然后在这些子序列内分别进行直接插入排序,当整个序列都基本有序时,再对全体记录进行一次直接插入排序。
基本有序:基本有序的意思就是小的关键字基本在前面,大的基本在后面,不大不小的基本在中间。像{2,1,3,6,4,7,5,8,9};但像{2,9,3,6,4,7,5,8,1}9在第二位,1在倒数第一位就谈不上基本有序。
分割策略:将相距某个“增量”的记录组成一个子序列,这样才能保证子序列内分别进行直接插入排序后得到的结果是基本有序而 不是局部有序;应当注意增量序列的最后一个增量值必须等于1才行。
代码:
#include<stdio.h>
#include<stdlib.h>
void Shell(int arr[], int len, int dk)//对一个分组中的序列使用直接插入排序算法
{
int tmp = 0;
int i = dk;
int j = i - dk;
for (i; i < len; ++i)
{
tmp = arr[i];
for (j = i - dk; j >= 0 && arr[j] > tmp; j -= dk)
{
arr[j + dk] = arr[j];
}
arr[j + dk] = tmp;
}
}
void ShellSort(int arr[], int len, int dk[], int dlen)
{
for (int i = 0; i < dlen; ++i)
{
Shell(arr, len, dk[i]);
}
}
int main2()
{
int arr[] = { 3, 12, 4, 32, 5, 436, 5, 47, 65, 8, 67, 84, 5, 234, 12 };
int len = sizeof(arr) / sizeof(arr[0]);
int dk[] = { 5, 3, 1 };//增量
int dlen = sizeof(dk) / sizeof(dk[0]);
ShellSort(arr, len, dk, dlen);
return 0;
}
希尔排序时间复杂度分析:
希尔排序的关键并不是随便分组后各自排序,而是将相隔某个“增量”的记录组成一个子序列,实现跳跃式的移动,使得排序的效率提高。迄今为止没有人找到一种最好的增量序列。不过大量的研究表明当增量序列为
可以获得不错的效率,其时间复杂度为。平均情况是Onlogn~O(n2)。