一、引入希尔排序
通过理解直接插入排序的算法,我们可以发现算法的时间耗费主要在查找合适位置和移动元素为待排元素腾位置。
因此,直接插入排序算法,在待排序的元素序列基本有序且序列元素较少时,其性能最佳!
而希尔排序就是利用了直接插入排序最佳性能的两个性质,因为它可以通过算法实现使序列越来越有序(不到最后
一步,都不是真正有序)且元素较少!所以在时间耗费上,希尔排序较直接插入排序性能有较大的改进!
二、希尔排序算法思路:
说算法思路之前,我想应该先介绍一下什么是增量序列!
所谓增量序列,就是一列数!这一列数的作用就是用来为待排序序列分组用的,而且这个序列有个特点:最后一
个元素必须是1!
举例子如下图:
由上图可以很简单总结出希尔排序算法思路:
就是将整个待排序的大序列通过增量序列分解为多个小序列,然后对每个小序列进行直接插入排序。如此反复多次(次数与增量序列有关,增量序列有多少个元素,就反复多少次)。等到按照所有增量序列元素所分的每个小序列都进行直接插入排序后,序列即被排好序!
三、源代码实现:
/*
**功能: 对一个增量产生的所有序列进行直接插入排序
**参数说明:
**@record : 待排序列数组 @len : 待排序列长度
**@delta : 此次划分子序列的增量
**返回值 : 无
*/
void ShellInsertSort(int record[], int len, int delta)
{
int i = 0, j;
int value; //保存待插入的元素的值
//0+delta 为第一个子序列的第二个元素的下标(直接插入排序是从序列的第二个元素开始的)
// i 每次自增以后都会是某一个子序列的第二个元素或之后的元素的下标。
for (i = 0 + delta; i < len; i++)
{
if (record[i] < record[i - delta])
{//该子序列未有序
value = record[i];
//为value寻找合适的插入位置(移动元素)
for (j = i - delta; j >= 0 && value < record[j]; j -= delta)
{
record[j + delta] = record[j];
}
//将value插入合适的位置
record[j + delta] = value;
}
}
}
/*
**功能: 希尔排序算法升序排序一个序列
**参数说明:
**@record : 序列数组 @len : 序列长度
**@delta : 增量序列数组 @n : 增量序列长度
**返回值: 无
*/
void ShellSort(int record[], int len, int delta[], int n)
{
int i;
for (i = 0; i < n;i++)
{
ShellInsertSort(record, len, delta[i]); //对一个增量产生的所有序列进行直接插入排序
}
}
int main(void)
{
int record[] = { 46,55,13,42,94,17,05,70 }; //待排序列数组
int delta[] = { 4,2,1 }; //增量数组
int len = sizeof(record) / sizeof(record[0]);
int n = sizeof(delta) / sizeof(delta[0]);
int i = 0;
printf("排序前: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
ShellSort(record, len, delta, n);
printf("排序后: \n");
for (i = 0;i < len;i++)
{
printf("%d ", record[i]);
}
puts("");
return 0;
}
运行截图: