排列的逆

将排列(abcdef)应用(cdfbea),那么它的逆为(cdfbea)应用(abcdef)等价于(abcdef)应用(fdabec)

所以(cdfbea)的逆为(fdabec)

算法A流程

  E1.获取当前的替代X,X[i]表示i被X[i]代替,将m从1到n遍历(全部遍历,与起始点无关),设j为任意负值.

  E2.获取当前的i=X[m],如果当前X[m]<0,则X[m]取自身相反数,去E5.

  E3.当前X[m]大于0,X[m]=j,j=-m,m=i,i=X[m].

  E4.i>0,则回E3;否则将X[m]=-j;

  E5.m自增加1.如果m>n,算法结束.

证明

  某排列的逆可以分为1~n个部分,每个部分可以看作一个环.通过遍历,对于每个点所在的环,要么已经遍历过要么没有遍历过,对于没有遍历过的,一开始这个环上的某个节点会获得一个任意的负值(j),然后将当前的-m赋给X[X[m]],由于是环路最终一定存在X[X[m]]=j。而这个过程中所有-m均赋值给X[X[m]],只有最后一个-m没有赋值,而恰好这个-m是我们一开始遍历这个环的某个节点的最终值,同时在这个过程中,这个环路上其他的节点都已经赋过值,因此对于没有遍历过的环上的节点只要先处理一个节点,其他节点的值就会随之计算出来。

代码实现

void PermutationInvertingA(char *SrcStr)
{
    int m,Len,i,j;
    Len=strlen(SrcStr);
    int *X=(int *)malloc((Len+1)*sizeof(int));
    for(i=0;i<Len;++i)
    {
        X[i+1]=SrcStr[i]-'a'+1;
    }
    for(m=1,j=-1;m<=Len;++m)
    {
        i=X[m];
        if(i<0)
        {
            X[m]=-i;
            continue;
        }
        if(i==m)
        {
            continue;
        }
        while(i>0)
        {
            X[m]=j;
            j=-m;
            m=i;
            i=X[m];
        }
        X[m]=-j;
    }
    for(i=1;i<=Len;++i)
    {
        printf("%d ",X[i]);
    }
    printf("
");
    free(X);
}
View Code

 算法B流程

  E1.获取当前的X[i],X[i]表示i要被X[i]代替,然后将所有的X[i]=-X[i],将m从1到n开始遍历(全部遍历,与起始点无关)

  E2.将m赋给j

  E3.i=X[j],如果i>0,将j=i,重复E3.

  E4.X[j]=X[-i],X[-i]=m

  E5.m自增加1,如果m>n算法结束

证明

  撤销操作不同环之间的操作是不影响,所以我们只需要看一个环就行,假设当前X[i](1<=i<=n)为

  X[1]=-3,X[2]=-1,X[3]=-4,X[4]=-2(环为1->3->4->2->1)

  具体流程就为:

  将1指向的操作撤销,将X[3]原值赋给X[1],X[3]=1

  得到X[1]=-4,X[2]=-1,X[3]=1,X[4]=-2

  将2指向的操作撤销,X[2]=-4,X[1]=2

  得到X[1]=2,X[2]=-4,X[3]=1,X[4]=-2

  将3指向的操作撤销,由于当前X[3]为正数,根据X[3]当前的值找到了X[1],因为X[3]的原值赋给了X[1],然后有找到了X[2],就有X[2]=-2,X[4]=3

  得到X[1]=2,X[2]=-2,X[3]=1,X[4]=3

  将4指向的操作撤销,先找X[4],然后找X[3],然后找X[1],然后找X[2],就有X[2]=-2,X[2]=4

  得到X[1]=2,X[2]=4,X[3]=1,X[4]=3

  算法每一次是为了撤销当前的数指向的操作,然后逐步构造出最终的图(排列)

代码实现

void PermutationInvertingB(char *SrcStr)
{
    int m,Len,i,j;
    Len=strlen(SrcStr);
    int *X=(int *)malloc((Len+1)*sizeof(int));
    for(i=0;i<Len;++i)
    {
        X[i+1]=-(SrcStr[i]-'a'+1);
    }
    for(m=0;m<=Len;++m)
    {
        j=m;
        while(i=X[j],i>0)
        {
            j=i;
        }
        X[j]=X[-i];
        X[-i]=m;
    }
    for(i=1;i<=Len;++i)
    {
        printf("%d ",X[i]);
    }
    printf("
");
    free(X);
}
View Code
原文地址:https://www.cnblogs.com/NoSoul/p/3304111.html