康托展开在全排列中使用(C++实现)

  1. 在一个全排列中,比如在1,2,3,4,5所有的全排列中,如何确定34152在1,2,3,4,5所欲排列中排第几?
  2. 康托展开的公式为以1,2,3,4,5为例,那么康托展开的公式为
  3. X=a[5](5-1)!+a[4](4-1)!+a[3](3-1)!+a[2](2-1)!+a[1]*(1-1)
  4. 其中1<=a[i]<=5,a[i]表示(从首位开始算)指的是位于位置i后面的数小于a[i]值的个数。比如34152的康托展开式子为:
  5. 首位3在所有未出现的数字中排第3(1,2)
    所以a[5]=2(小于3的有2个)
    第二位4在所有未出现的数字中排第三(1,2)
    所以a[4]=2(小于4的有2个)
    同理a[3]=0 a[2]=1 a[2]=0
    X=a[5](5-1)!+a[4](4-1)!+a[3](3-1)!+a[2](2-1)!+a[1](1-1)!
    X=2
    4!+23!+02!+11!+00!
    X=61
    那么在34152小的全排列有61个,那么34152排在全排列的第62个。康托展开就是上述的描述。当然还有康托展开的逆运算。也是很有用的。C++代码实现如下所示:
    #include
    using namespace std;
    int getSmaller(int intarr, int key)//计算位置比key小的,标志位为1(说明没有参与康拓计算过的数字)的个数。
    {
    int sum = 0;
    for (int i = 1; i < key; i++)
    {
    if (intarr[i] == 1)
    {
    sum++;
    }
    }
    return sum;
    }
    int jiecheng(int n)//计算N的阶乘
    {
    if (n == 1 || n == 0)
    {
    return 1;
    }
    else
    {
    return n
    jiecheng(n - 1);
    }
    }
    int getCantor(int number, int length)
    {
    int len = length + 1;
    int *numflag = new int[len];//定义标志为函数,标志i位是否已经参与过康拓计算。1为没参与过
    for (int i = 1; i < len; i++)
    {
    numflag[i] = 1;
    }
    int numarr = new int[len];
    int temp = number;
    for (int i = 1; i < len; i++)//把所有数字通过求余运算放到一个数组里面,便于后序康拓展开运算。
    {
    numarr[i] = temp%10;
    int ai = temp % 10;
    temp = temp / 10;
    }
    int cantornum = 0;
    for (int i = len - 1; i >= 1; i–)
    {
    int key = numarr[i];
    int ai = getSmaller(numflag, key);//获取位置比key小的,个数。
    numflag[key] = 0;//当改为参与过康拓展开计算时,标志位设为1;
    int aikey = jiecheng(i - 1);
    cantornum += ai
    aikey;//计算康托展开
    }
    return cantornum+1;
    }
    int main()
    {
    cout << getCantor(34152,5) << endl;
    system(“pause”);
    return 0;
    }
    康托展开在全排列的计算中有重要的作用,比如字符串全排列的的字典序的排序等等运算。通过康托展开我们可以迅速确认一个全排顺序的位置,年与后续的计算和处理
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值