这几天在做关于排序的题目。作为插入排序的扛把子——希尔排序,还是需要复习复习。直接插入排序,当待排序的记录个数较少且待排序序列的关键字基本有序时,效率较高。希尔排序基于以上两点,从减少记录个数和序列基本有序两个方面对直接插入排序进行了改进。
[算法步骤]
希尔排序实质上是采用分组插入的方法。先将整个待排序记录分割成几组,从而减少参与直接插入排序的数据量,对每组分别进行直接插入排序,然后增加每组的数据量,重新分组。这样当几次分组排序后,整个序列中的记录“基本有序”时,再 对全体记录进行一次直接插入排序。
希尔对记录的分组,不是简单地“逐段分割”,而是将相隔某个“增量”的记录分成一组。
1.第一趟取增量的d1把全部记录分成d1个组,所有间隔d1的记录分在同一组,在各个组中进行直接插入排序。
2.第二趟取增量d2(d2<d1)重复上述的分组和排序。
3.依次类推,直到所取的增量d=1,所有记录在同一组中进行直接插入排序为止。
[算法描述]数据结构伪代码实现
void ShellInSert(SqList &L,int dk)
{//对顺序表L做一趟增量是dk的希尔插入排序
for(i=dk+1;i<=L.length;i++)
if(L.r[i].key<L.r[i-dk].key)
{
L.r[0]=L.r[i];
for(j=i-dk; j>0&& L.r[0].key<L.r[j].key;j=j-dk)
L.r[j+dk]=L.r[j];
L.r[j+dk]=L.r[0];
}
}
void ShellSort(SqList &L,int dt[],int t)
{//按增量序列dt[0..t-1]对顺序表L做t趟希尔插入排序
for(k=0;k<t;k++)
ShellInsert(L,dt[k]);
}
[算法特点]
1.不稳定
2.只能用于顺序结构
3.适合初始记录无序,n较大的情况。
算法代码
希尔排序算法代码如下:
voidShellSort(SqList*L)
{
inti,j;
int dk=L->length;
do
{
dk=dk/3+1;/*增量序列*/
for(i=dk+1;i<=L->length;i++)
{
if(L->r[i]<L->r[i-dk)/*需将L->r[i]插入有序增量子表*/
{
L->r[0]=L->r[i];/*暂存在L->r[0]*/
for(j=i-dk;j>0&&L->r[0]<L->r[j];j-=dk)
L->r[j+dk]=L->r[j];/*记录后移,查找插入位置*/
L->r[j+dk]=L->r[0];/*插入*/
}
}
}
while(dk>1);
}