对康拓展开式和逆康托展开式的认识

人的理解能力真的变化很大,之前看着很迷茫的东西先在看来简单不少(其实是以前太菜了*-*)

康托展开式——据说是用来构建哈希表时的空间压缩,其他的什么用途我还不知道,希望有菊苣告诉我

康拓展开式最简单的用途是求一个数在这个数的全排列中(从小到大)的第几个(最小的是第0个,这个在之后会解释,还会用到)

说的不是很清楚,我们还是来看例子吧比如要知道45321在由1,2,3,4,5组成的数的第几个计算如下

X=3*4!+3*3!+2*2!+1*1!+0*0!=95解释下这个式子吧。。。。。。。。。。。。

第一个数字是4,比4小的有3个:1,2,3,由1开始的数字有4!个一共就有3*4!个

第二个数字是5,比5小的有4个,但是4已经用过了所以只有1,2,3,由1为第二位的数(第一位已经考虑完了)有3!个;

接下来类似就能完成了,读者可以自己写一个数算算,也可以跟着代码理解下

我们将12345用上述方法计算得0所以最小是0开始的就可以解释了

int cantor(int a[],int n)//a数组是给出的数,n是元素个数 
{
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int k=0;//统计有多少数比a[i]小 
        for(int j=i+1;j<=n;j++)
            if(a[i]>a[j]) k++;
        ans+=k*fac(n-i);//fac函数是计算阶乘的,这里就不写了 
    }
    return ans;
}

逆康拓展开式就是康托展开式的逆运算。。。。给定元素要你计算第n个的排列是什么

我们还是用45321来解释。

要求1,2,3,4,5排列的第96个的数,由于是从0开始的,所以我们在计算前先-1;

96/(4!)=3------23有三个数比它小的数是4

23/(3!)=3------5有三个数比它小的数是4,但是由于4之前已经用过了,所以实际上这时第四大的数是5;

5/(2!)=2-------1有两个数比它小的数是3

1/(1!)=1有一个数比它小的数是2

最后以为只能是1了

int cantor_reverse(int k,int n,int b[])//a数组是给出的数,n是元素个数 
{
    k--;
    int v[23];//记录数字的使用情况 
    memset(v,0,sizeof(v));
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int m=k/fac(n-i);
        k%=fac(n-i);
        for(int j=1;j<=m;j++)
        {
            if(v[j]) //如果有比他小的数已经用过了
                m++;
        }
        b[i]=m+1;
        v[m]=1;
    } 
}

总之麻打麻打达内..........加油吧!

原文地址:https://www.cnblogs.com/Oremix/p/7103505.html