希尔排序增量序列简介

希尔排序可谓是时间复杂度较难分析的一类排序算法之一,其原因在于其增量序列的多样性和构造的复杂性。下面笔者将对几种流传较广的希尔排序的增量序列进行简单的介绍并给出它们的实现代码。

希尔排序主过程代码如下:

#define ShellSort(IncrementName,delta) \
{ \
    for(int d=delta>0?1:IncrementSequence_##IncrementName[0]; \
        delta>0&&d<=IncrementSequence_##IncrementName[0]||delta<0&&d>0;d+=delta) \
        for(int sub=IncrementSequence_##IncrementName[d]+1;sub<=n;sub++) \
        { \
            int obj,temp=array[sub]; \
            for(obj=sub;obj>IncrementSequence_##IncrementName[d] \
                &&array[obj-IncrementSequence_##IncrementName[d]]>temp; \
                obj-=IncrementSequence_##IncrementName[d]) \
                array[obj]=array[obj-IncrementSequence_##IncrementName[d]]; \
            array[obj]=temp; \
        } \
}

Shell 增量序列

Shell 增量序列的递推公式为:

ht=N2,hk=hk+12

Shell 增量序列的最坏时间复杂度为 Θ(N2)

Shell 增量序列构造代码如下:

int IncrementSequence_Shell[35];
void IncrementSequenceBuild_Shell()
{
    IncrementSequence_Shell[0]=1;
    IncrementSequence_Shell[1]=n;
    while(IncrementSequence_Shell[IncrementSequence_Shell[0]]>1)
        IncrementSequence_Shell[++IncrementSequence_Shell[0]]=IncrementSequence_Shell[IncrementSequence_Shell[0]-1]/2;
}

调用代码如下:

IncrementSequenceBuild_Shell();
ShellSort(Shell,1)

Hibbard 增量序列

Hibbard 增量序列的通项公式为:

hi=2i1

Hibbard 增量序列的递推公式为:
h1=1,hi=2hi1+1

Hibbard 增量序列的最坏时间复杂度为 Θ(N3/2) ;平均时间复杂度约为 O(N5/4)

Hibbard 增量序列构造代码如下:

int IncrementSequence_Hibbard[35];
void IncrementSequenceBuild_Hibbard()
{
    IncrementSequence_Hibbard[0]=30;
    IncrementSequence_Hibbard[1]=1;
    for(int i=2;i<=30;i++)
        IncrementSequence_Hibbard[i]=IncrementSequence_Hibbard[i-1]*2+1;
}

或者直接打表:

int IncrementSequence_Hibbard[]={30,
    1,3,7,15,31,63,127,255,
    511,1023,2047,4095,8191,16383,32767,65535,
    131071,262143,524287,1048575,2097151,4194303,8388607,16777215,
    33554431,67108863,134217727,268435455,536870911,1073741823};

调用代码如下:

IncrementSequenceBuild_Hibbard();
ShellSort(Hibbard,-1)

Knuth 增量序列

Knuth 增量序列的通项公式为:

hi=12(3i1)

Knuth 增量序列的递推公式为:
h1=1,hi=3hi1+1

Knuth 增量序列构造代码如下:

int IncrementSequence_Knuth[25];
void IncrementSequenceBuild_Knuth()
{
    IncrementSequence_Knuth[0]=20;
    IncrementSequence_Knuth[1]=1;
    for(int i=2;i<=20;i++)
        IncrementSequence_Knuth[i]=IncrementSequence_Knuth[i-1]*3+1;
}

或者直接打表:

int IncrementSequence_Knuth[]={20,
    1,4,13,40,121,364,1093,3280,
    9841,29524,88573,265720,797161,2391484,7174453,21523360,
    64570081,193710244,581130733,1743392200};

调用代码如下:

IncrementSequenceBuild_Knuth();
ShellSort(Knuth,-1)

Gonnet 增量序列

Gonnet 增量序列的递推公式为:

ht=N2.2,hk=hk+12.2(h2=2h1=1)

Gonnet 增量序列构造代码如下:

int IncrementSequence_Gonnet[30];
void IncrementSequenceBuild_Gonnet()
{
    IncrementSequence_Gonnet[0]=1;
    IncrementSequence_Gonnet[1]=n;
    while(IncrementSequence_Gonnet[IncrementSequence_Gonnet[0]]>1)
        IncrementSequence_Gonnet[++IncrementSequence_Gonnet[0]]=IncrementSequence_Gonnet[IncrementSequence_Gonnet[0]-1]/2.2;
    IncrementSequence_Gonnet[IncrementSequence_Gonnet[0]]=1;
}

调用代码如下:

IncrementSequenceBuild_Gonnet();
ShellSort(Gonnet,1)

Sedgewick 增量序列

Sedgewick 增量序列的通项公式为:

hi=max(94j92j+1,4k32k+1)

Sedgewick 增量序列的最坏时间复杂度为 O(N4/3) ;平均时间复杂度约为 O(N7/6)

Sedgewick 增量序列构造代码如下:

int IncrementSequence_Sedgewick[30];
void IncrementSequenceBuild_Sedgewick()
{
    IncrementSequence_Sedgewick[0]=28;
    IncrementSequence_Sedgewick[1]=1;
    for(int i=1,j=2;i<=13||j<=15;)
        if(i<=13&&9*(1<<i*2)-9*(1<<i)+1<(1<<j*2)-3*(1<<j)+1)
            IncrementSequence_Sedgewick[i+j-1]=9*(1<<i*2)-9*(1<<i)+1,i++;
        else
            IncrementSequence_Sedgewick[i+j-1]=(1<<j*2)-3*(1<<j)+1,j++;
}

或者直接打表:

int IncrementSequence_Sedgewick[]={28,
    1,5,19,41,109,209,505,929,
    2161,3905,8929,16001,36289,64769,146305,260609,
    587521,1045505,2354689,4188161,9427969,16764929,37730305,67084289,
    150958081,268386305,603906049,1073643521};

调用代码如下:

IncrementSequenceBuild_Sedgewick();
ShellSort(Sedgewick,-1)
  • 11
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值