首页 > 编程知识 正文

康托展开的用途,康托展开式

时间:2023-05-06 11:57:46 阅读:186560 作者:298

铁路超高发展概况:官方简介:

康托展开是完全按自然数排列的双射,常用于构建散列表时的空间压缩。 铁路超展开的本质是计算当前从小到大所有数组中的顺序,其是可逆的。

通俗简介:

在纸箱展开中,例如,可以求出数组的编号,在该数组中,12345的号码为1,12345的号码为2,按照字典顺序将号码增加,依次类推。

康托反展开可以解开一个号码,与之对应的排列是什么?

铁路超高展开解释:给出铁路超高展开的公式:

首先说明这个公式中的变量。 大家不理解这个公式也没关系。 慢慢地看后面。 很简单。

的意思是,从右向左第I个位数是这个数之前没有出现的数,是最大的。 举例来说,你可以看到这个公式:

注意:在计算时,12345序列应视为第0序列,其理由将在后面叙述。

以52413为例:

1、首先请看第一位的数5。 不管第一位是什么数,后面都有四位。 那么,这4位的全部排列方法是4。 因为种类比第一位是1、2、3、4或5开始的词典顺序小,所以如果把1、2、3、4分别作为开头的话就是4 * 4! 排列法比52413这样的排列法的词典顺序小。

那么,最初的数是1、2、3、4时的词典顺序的数完是4 * 4! 种,而且这些字典的顺序都小于52413的字典的顺序。

还有其他比52413的词典顺序小的排列吗?

2、那么可以固定第一位的5,找下一位的2。 此时,因为5已经用过了,所以从剩下的1、2、3、4中选出小于2的数,一共一个,后面剩下的三个,也就是3! 考虑到排列方式,这个时候比52413字典小的还有1 * 3! 种子,也就是5是第一位,1是第二位的时候。

看看第三个4。 此时,5、2都使用了,所以从剩下的1、3、4的3个数中寻找小于4的数,与有2个小于4的数的原理相同,所以此时也可以有2 * 2。 种排列方式的词典顺序小于52413

看看第四名第一名。 这时,有0 * 1! 种

看五、五位三,这个时候有0 * 0! 种

综上所述:

序列: 52413展开这个序列,就是4 * 4! 1 * 3! 2 * 2! 0 * 1! 0 * 0! 的计算结果是106

因为是从0开始计数,所以最后52413的号码是107

为什么要从0开始计数?

可以这样看。 现在,让我求出12345的纸箱展开值。 也就是说0*4。 0*3! 0*2! 0*1! 0*0!=0,所以你明白了吧~

康托表达式的最小词典顺序编号为0。

铁路超高展开代码:/*****此处通过以字符串形式显示字符串来实现高度通用性* * * */# include iostream # include cstdio # include vector # includealgorithmusior voidJie_Cheng(intn ) { f[0]=f[1]=1; //0的阶乘为1for(intI=2; i=n; I ) f(I )=f(I-1 ) *I; () ) )、铁路超高展开(,(,(,(,(,),)、)、()、(,)、()、)、)、()、()、()、()、()、)、(stringstr; int kangtuo () { int ans=1; //注意,12345数为0开始计算,所以最后的结果是12345为最初的int len=str.length (); for(intI=0; i len; I ) { int tmp=0; //用于计数的for(intj=I1; j len; j () if ) str[I]str[j] ) tmp; 计算str[i]是第几个大的数,或者有几个比他小的数(} ans =tmp * f[len - i - 1]; } return ans; }int main () Jie_Cheng ) 10; string str='52413 '; coutkangtuo () endl; (康托反向展开解释)这里直接打开栗子。

如果初始数组是12345(1 (第一个),则系统会提示您输入第107个数组是什么。 (按词典顺序递增)

这样计算:

请先从107减去1。 因为铁路超高展开的初始序列号是0

然后计算后缀积。

1 2 3 4 5

5! 4! 3! 2! 1! 0!

120 24 6 2 1 1

106 /  4! = 4 ······ 10 有4个比它小的所以因该是5   从(1,2,3,4,5)里选
10   /  3!  = 1 ······ 4  有1个比它小的所以因该是2   从(1, 2, 3, 4)里选
 4    /  2!  = 2 ······ 0  有2个比它小的所以因该是4   从(1, 3, 4)里选
 0    /  1!  = 0 ······ 0  有0个比它小的所以因该是1   从(1,3)里选
 0    /  0!  = 0 ······ 0  有0个比它小的所以因该是3   从(3)里选

所以编号107的是 52413

康托逆展开代码: /***** 这里以字符串进行展示 字符串可泛化性好 ******/#include<iostream>#include<cstdio>#include<vector>#include<algorithm>using namespace std;/*******打出1-n的阶乘表*******/int f[20];int x, num;void jie_cheng(int n){ f[0] = f[1] = 1; // 0的阶乘为1 for(int i = 2; i <= n; i++) f[i] = f[i - 1] * i;}/**************康托逆展开**************/vector<char> vec; //存需要排列的字符void rev_kangtuo(int k) //输出序号为 k 的字符序列{ int n = vec.size(), len = 0; string ans = ""; k--; // 算的时候是按 12345 是第0位 for(int i = 1; i <= n; i++){ int t = k / f[n - i]; // 第 i 位需要 第 t + 1 大的数 k %= f[n - i]; //剩下的几位需要提供的排列数 ans += vec[t] ; // vec[t] 就是第 t + 1 大的数 vec.erase(vec.begin() + t); //用过就删了,不用vector用暴力也可以,就是说枚举,然后一个一个的比较大小,并记录有几个没用过的字符且字典序比它小 } cout << ans << 'n';}/***************************************/// 假设展开后不超过10位int main(){ jie_cheng(10); // 预处里好阶乘 scanf("%d", &x); // 输入需要逆展开的数字 /************康托逆展开***********/ for(int i = 1; i <= 10; i++) { if(x / f[i] == 0) // 求出 x 逆展开所需的最小的位数,方便下面的初始化 { num = i; break; } } for(int i = 1; i <= num; i++) vec.push_back(i + '0'); //输入的位数只要不小于num就可以 rev_kangtuo(x);}

 

 

 

 

 

 

 

 

 

 

 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。