shell(希尔)排序是一种插入排序算法,它出自D.L.Shell,因此而得名。Shell排序又称作缩小增量排序。
shell(希尔)排序是面试出现次数较多且较难理解的,是插入排序(插入排序链接)的改进版,排序效率更快。
基本思想
shell(希尔)排序就是将依次将一组数字进行对半分组,每一组对应下标(下标就是该数在数组中存放的位置,从0开始)的数字形成插入排序(例如分组为4组,每组对应的数字,如a[0],b[0],c[0],d[0]进行一次插入排序),直到分组分到每个数字一组(即数组的所有数字进行一次插入排序)完成shell排序。
举例
第一次排序
分组后共有6(元素总数/分组次数)组数字进行插入排序:
两组第一个数字 23,53
两组第二个数字 64,71
两组第三个数字 87,57
两组第四个数字 12,97
两组第五个数字 9 ,24
两组第六个数字 16,79
第二次排序
分组后共有3(元素总数/分组次数)组数字进行插入排序
四组第一个数字 23,12,53,97
四组第二个数字 64, 9,71,24
四组第六个数字 57,16,87,79
第三次排序
分组后共有1(元素总数/分组次数)组数字进行插入排序
12,64,87,12,9,16,53,71,57,97,24,79
排序过程
流程如下:
1.对数组进行对半分组
2.每一分组对应下标的元素组成一个数组,进行插入排序
3.直到每个元素为1组
C语言实例
int shell_sort(int *data, int length)
{
int gap = 0; //分组的跨度
int i = 0, j = 0,k = 0,z = 0;
for (gap = length / 2; gap >= 1;gap /= 2) { // 分组的次数
for(i = 0; i < gap; i ++) { // 每组遍历,即分组后对应元素的插入排序次数
#if 1 //if语句内就是插入排序
for(k = i + gap; k < length;k += gap) { //对每组对应下标元素依次比较
if(data[k] < data[k-gap]) {
int temp = data[k];
//依次把前面的数向后移一位,直到找到比该数小的数
for(z = k - gap;z >= 0 && data[z] > temp;z -= gap) {
data[z+gap] = data[z];
}
data[z+gap] = temp;
}
}
#endif
}
}
return 0;
}
下面是代码优化的写法
排序过程
C语言实例
int shell_sort(int *data, int length)
{
int gap = 0; //每次分组组内的元素个数
int i = 0,j = 0
for (gap = length / 2; gap >= 1;gap /= 2) { // 分组的次数,每次分组有length/2个元素
for(i = gap; i < length; i ++) { // 每组遍历
int temp = data[i]; //存储要替换的元素
for (j = i - gap; j >= 0 && temp < data[j];j = j - gap) { //每组下标对应的元素比较
data[j+gap] = data[j]; //如果temp比后面的值小,那么把temp插入到前面
}
data[j+gap] = temp; //如果temp比前面的值大,没有变化;
//如果temp比前面的值小,把temp放到前面
}
}
return 0;
}
总结
shell(希尔)排序每次分组都把(相对)小的放前面的分组,(相对)大的放后面的分组,最后一次分组是整个数组的插入排序,其实就是减少了最后一次插入排序的移位次数。