- 在一个全排列中,比如在1,2,3,4,5所有的全排列中,如何确定34152在1,2,3,4,5所欲排列中排第几?
- 康托展开的公式为以1,2,3,4,5为例,那么康托展开的公式为
- X=a[5](5-1)!+a[4](4-1)!+a[3](3-1)!+a[2](2-1)!+a[1]*(1-1)
- 其中1<=a[i]<=5,a[i]表示(从首位开始算)指的是位于位置i后面的数小于a[i]值的个数。比如34152的康托展开式子为:
- 首位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=24!+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 njiecheng(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 += aiaikey;//计算康托展开
}
return cantornum+1;
}
int main()
{
cout << getCantor(34152,5) << endl;
system(“pause”);
return 0;
}
康托展开在全排列的计算中有重要的作用,比如字符串全排列的的字典序的排序等等运算。通过康托展开我们可以迅速确认一个全排顺序的位置,年与后续的计算和处理
康托展开在全排列中使用(C++实现)
最新推荐文章于 2022-03-26 19:16:07 发布