自己看书时,对希尔排序的理解一直处于茫然状态,然后在维基百科上看到了这样一句话,再加上这样一个例子,总算消除了我的迷惑。
因为访问危机百科需要翻墙,故复制了了相关内容在本博客里,若读者已翻墙,可以直接点此进入维基百科查看。
--------------------------------------以下内容来源于维基百科--------------------------------------
一个更好理解的希尔排序实现:将数组列在一个表中并对列排序(用插入排序)。重复这过程,不过每次用更长的列来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身仅仅对原数组进行排序(通过增加索引的步长,例如是用i += step_size
而不是i++
)。
例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:
13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10
然后我们对每列进行排序:
10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45
将上述四行数字,依序接在一起时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:
10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45
排序之后变为:
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
最后以1步长进行排序(此时就是简单的插入排序了)。
--------------------------------------以上内容来源于维基百科--------------------------------------
值得注意的是,在希尔排序里,注意选择增量因子,最后一个增量因子必须是1,其次各增量之间不应该含有公约数,或者说各个增量互素。
下面是我的实现代码,其中考虑了增量排序的问题,避免输入有误。这个代码是为了学习插入排序而写的,本来增量因子排序那个直接插入排序函数是可以省的,我还是写上了。便于与希尔排序做个比较。
#include<stdio.h>
#define MaxSize 100
struct DataType
{
int data;
};
struct Sqlist
{
DataType R[MaxSize];
int length;
};
//直接插入排序对增量因子由大到小排序
void DirectSort(int *da,int n)
{
int i,j;
int temp;
for(i=1;i<n;i++)
{
if(da[i-1] < da[i])
{
temp = da[i];//设置temp为哨点
j=i-1;
while(da[j] < temp)
{
da[j+1] = da[j];
j--;
if(j<0)
{
break;
}
}
da[j+1] = temp;
}
}
}
void ShellInsert(Sqlist *l,int d)
{
//对R数组进行希尔排序,d为增长因子
int i,j;
for(i=d+1;i<=l->length;i++)
{
if(l->R[i].data > l->R[i-d].data)
{
//向前寻找插入位置
l->R[0] = l->R[i];//置哨点
j = i-d;
while(l->R[0].data > l->R[j].data)
{
l->R[j+d] = l->R[j];
j=j-d;
if(j<0)
{
break;
}
}
l->R[j+d] = l->R[0];
}
}
}
//希尔排序
void ShellSort(Sqlist *l)
{
//按递增序列对顺序表R数组做希尔排序
int d[10],t,k;
printf("\n输入增量因子的个数:");
scanf("%d",&t);
printf("由大到小输入每一个增量因子:\n");
for(k=0;k<t;k++)
{
scanf("%d",&d[k]);
}
//对增量因子进行排序,以防出错
DirectSort(d,t);
for(k=0;k<t;k++)
{
printf("%d ",d[k]);
}
printf("\n");
for(k=0;k<t;k++)
{
ShellInsert(l,d[k]);
}
}
int main()
{
Sqlist list;
list.length = 10;
int data[10] = {2,6,1,4,9,6,8,7,3,9};
//初始化数据
for(int i=0;i<list.length;i++)
{
list.R[i+1].data = data[i];
}
ShellSort(&list);
for(int i=0;i<list.length;i++)
{
printf("%d ",list.R[i+1].data);
}
}
运行截图: