#希尔排序是一种属插入排序类的方法。
它的基本思想是:先将整个待排记录序列分割成为若干子序列,分别对其进行直接插入排序,不断重复上述步骤,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
#本博客采用顺序表结构体如下,0号单元留空
typedef struct
{
int *r;
int length;
int listsize;
}SqList;//构造顺序表结构体类型
#直接插入排序及解析
void InsertSort(SqList &L)
{
int i,j;
for(i=2;i<=L.length;i++)//从第2个元素开始,逐一向前进行插入
{
if(L.r[i]<L.r[i-1])//当待插入元素小于前一个元素时
{
L.r[0]=L.r[i];//将待插入元素放入0号单元
L.r[i]=L.r[i-1];//将前一个元素放入待插入元素的位置
for(j=i-2;L.r[0]<L.r[j];j--)//从前两个元素开始,依次往前,比较待插入元素与其的大小关系
{
L.r[j+1]=L.r[j];//当待插入元素小于第j个元素时,将第j个元素后移到j+1号单元
}
L.r[j+1]=L.r[0];//当待插入元素大于第j个元素时,将放在0号单元的待插入元素放在j+1号单元
}
}//每一次循环,将一个元素从未排序序列加入到已排序序列
}
#希尔排序以及解析
void ShellInsert(SqList &L,int dk)//以dk为增量进行一趟希尔排序
{
int i,j;
for(i=1+dk;i<=L.length;i++)//从1+dk个元素开始,逐一向前进行插入
{
if(L.r[i]<L.r[i-dk])//当待插入元素小于子序列中前一个元素时
{
L.r[0]=L.r[i];//将待插入元素放入0号单元
L.r[i]=L.r[i-dk];//将子序列中前一个元素放入待插入元素位置
for(j=i-2*dk;j>0&&L.r[0]<L.r[j];j=j-dk)//从子序列中前两个元素开始,依次在子序列中往前,比较待插入元素与其的大小关系
{
L.r[j+dk]=L.r[j];//当待插入元素小于第j个元素时,将第j个元素后移到j+dk号单元
}
L.r[j+dk]=L.r[0];//当待插入元素大于第j个元素时,将待插入元素放入j+dk号单元
}
}//每一次循环,将一个元素从子序列中的未排序序列加入到已排序序列
}//进行一趟希尔排序后,每个子序列变成单调有序递增序列
void ShellSort(SqList &L,int dlta[],int t)//按照增量数组dlta进行希尔排序
{
int k;
for(k=0;k<t;k++)
{
ShellInsert(L,dlta[k]);
}
}
很容易观察到,直接插入排序就是当dk=1时的一趟希尔排序。
唯一区别是,直接插入排序代码中少了j>0的防越界操作。因为dk=1时,j不再进行跳跃式前进,而是一步一步往前进。当放在0号单元的待插入元素很小很小时,j最终只会减为0,因为当j=0时,L.r[0]<L.r[j]不成立。
而当dk不等于1时,j进行跳跃式前进,L.r[0]不一定会与L.r[j]进行比较,此时就有可能越界了,所以必须加上j>0。
#测试结果
#本博客参考了《数据结构(C语言版)》(严蔚敏,吴伟民编著)