希尔排序 希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。直接插入排序 有一个问题如果待排序列中,顺序恰好是逆序,如果用直接插入排序,那将耗费大量的代价,每次都要移动大量 数据,付出非常惨重的代价。 因此 就诞生了 希尔排序, 这个排序方法,可以算是对 插入的一种改进。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。
排序思想: 先把 待排序列 分成若干组,对这若干组进行 插入排序,这样就 一部分 就先有序了, 之后 对这个组 在重新 划分 更小的若干组,进行插入排序, 直到组为1 的时候,退化为 直接插入排序。
初始时,有一个大小为 15 的无序序列。
(1)在第一趟排序中,我们不妨设 gap1 = N / 2 = 7,即相隔距离为 7 的元素组成一组,可以分为 5 组。
(2)接下来,按照直接插入排序的方法对每个组进行排序。
在第二趟排序中,我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2 = 3 (取整数)。这样每相隔距离为 2 的元素组成一组,可以分为 2 组。
(3)按照直接插入排序的方法对每个组进行排序。
(4)在第三趟排序中,再次把 gap 缩小一半,即gap3 = gap2 / 2 = 1。 这样相隔距离为 1 的元素组成一组,即只有一组。
(5)按照直接插入排序的方法对每个组进行排序。此时,排序已经结束。
下面 看一个例子:
int arr[]={1,34,6,21,98,31,7,4,36,16,47,67,37,25,2}
len=15 , gap=len/2
相同颜色代表一组.
先 组内 排序 为: {1 2 4},{34 36},{6 16},{21 47},{67 98},{31 37},{7 25}
1 4 2
34 36
6 16
21 47
98 67
31 37
7 25
下面看代码:
第一种实现 如下:
d 就是 gap 这个变量
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void printArray(int array[], int len)
{
int i = 0;
for(i=0; i<len; i++)
{
printf("%d ", array[i]);
}
printf("\n");
}
void shell_sort(int array[], int len){
int d = len;
while (1){
d = d/2;
for (int x=0;x<d;x++){
for (int i = x+d; i < len; i=i+d)
{
int k = i ;
int temp = array[k];
for (int j = i-d;j>=0 && array[j]>temp;j =j-d)
{
array[j+d] =array[j];
k = j ;
}
array[k] = temp ;
}
}
if (d ==1)//gap==1,跳出循环
{
break;
}
}
}
int main()
{
int array[]={1,34,6,21,98,31,7,4,36,25,2};
int len = sizeof(array) / sizeof(*array);
//printArray(array, len);
shell_sort(array, len);
printArray(array, len);
system("pause");
return 0;
}
看看第二种实现
把 组内排序 写成一个函数 ,这样看的更清楚一些。
#include "stdio.h"
#include "stdlib.h"
void printArray(int array[], int len)
{
int i = 0;
for(i=0; i<len; i++)
{
printf("%d ", array[i]);
}
printf("\n");
}
void group_sort(int array[], int len, int d,int x){
/*
array 数组的指针
len 数组的长度
d 组的步长 gap
x 组的起始位置
*/
for (int i = x+d; i < len; i=i+d)
{
int k = i ;
int temp = array[k];
for (int j = i-d;j>=0 && array[j]>temp;j=j-d)
{
array[j+d] =array[j];
k = j ;
}
array[k] = temp ;
}
}
/*
* 希尔排序
*
* 参数说明:
* array -- 待排序的数组
* len -- 数组的长度
*/
void shell_sort(int array[], int len)
{
int i,gap;
// gap为步长,每次减为原来的一半。
for (gap = len / 2; gap > 0; gap /= 2)
{
// 共gap个组,对每一组都执行直接插入排序
for (i = 0 ;i < gap; i++){
group_sort(array, len, gap,i);
}
}
}
int main()
{
int array[]={1,34,6,21,98,31,7,4,36,25,2};
int len = sizeof(array) / sizeof(*array);
//printArray(array, len);
shell_sort(array, len);
printArray(array, len);
system("pause");
return 0;
}
结果如下:
总结: 希尔排序 在一定程度 上减少了 交换次数, 但是这个和d 的递减因子有关。非常牛逼的算法,在此记录一下,如果有疑问可以一起讨论,交流。
参考文档:
c语言实现 shell 排序
http://www.cnblogs.com/denglw/p/6785654.html
希尔排序算法(排序详解) java 实现
http://blog.csdn.net/qq845579063/article/details/51447404
希尔排序详解
http://blog.csdn.net/z3881006/article/details/61922109
http://www.cnblogs.com/chengxiao/p/6104371.html
希尔排序 http://blog.csdn.net/MoreWindows/article/details/6668714
白话shell排序 http://www.cnblogs.com/skywang12345/p/3597597.html#a1
分享快乐,留住感动。 2017年 10月 18日 星期三 12:21:13 ----biaoge