模板 康拓展開和他的逆運算

2021-07-24 11:12:31 字數 2936 閱讀 1452

康托展開

康托展開的公式是 x = an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai為當前未出現的元素中是排在第幾個(從0開始),n指的是陣列的長度。

舉個例子,有乙個陣列 s = ["a", "b", "c", "d"],它的乙個排列 s1 = ["d", "b", "a", "c"],則

x(s1) = a4*3! + a3*2! + a2*1! + a1*0!

關鍵問題是 a4、a3、a2 和 a1 等於啥?

a4 = "d" 這個元素在子陣列 ["d", "b", "a", "c"] 中是第幾大的元素。("a"是第0大的元素,"b"是第1大的元素,"c" 是第2大的元素)"d"是第3大的元素,所以 a4 = 3。

a3 = "b" 這個元素在子陣列 ["b", "a", "c"] 中是第幾大的元素。"b"是第1大的元素,所以 a3 = 1。

a2 = "a" 這個元素在子陣列 ["a", "c"] 中是第幾大的元素。"a"是第0大的元素,所以 a2 = 0。

a1 = "c" 這個元素在子陣列 ["c"] 中是第幾大的元素。"c" 是第0大的元素,所以 a1 = 0。(因為子陣列只有1個元素,所以a1總是為0)

所以,x(s1) = 3*3! + 1*2! + 0*1! + 0*0! = 20

通過康托逆展開生成全排列

如果已知 s = ["a", "b", "c", "d"],x(s1) = 20,能否推出 s1 = ["d", "b", "a", "c"] 呢?

要根據x逆推出s1排列,我們只需要求出ai,ai的求法如下圖所示:

知道了a4、a3、a2、a1的值,就可以知道s1[0] 是子陣列["a", "b", "c", "d"]中第3大的元素 "d",s1[1] 是子陣列 ["a", "b", "c"] 中第1大的元素"b",s1[2] 是子陣列 ["a", "c"] 中第0大的元素"a",s[3] 是子陣列 ["c"] 中第0大的元素"c",所以s1 = ["d", "b", "a", "c"]。

以上內容參考自此部落格

附**(abcd長度n=4時,正推全排列的x值,逆推x值代表的全排列):

#include #include #include #include #include // x = an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

using namespace std;

const int maxn = 500;

int fac[maxn];

bool vis[26];//康托逆展開生成全排列時,記錄字母狀態

int n;

string s;

int cantor_fac(int x)

//通過排列求x

int cantor_encode()

for(int i=0; i=0; i--)

for(int i=0; i

原序列:abcd

x = 0

逆推序列:abcd(0000)

原序列:abdc

x = 1

逆推序列:abdc(0010)

原序列:acbd

x = 2

逆推序列:acbd(0100)

原序列:acdb

x = 3

逆推序列:acdb(0110)

原序列:adbc

x = 4

逆推序列:adbc(0200)

原序列:adcb

x = 5

逆推序列:adcb(0210)

原序列:bacd

x = 6

逆推序列:bacd(1000)

原序列:badc

x = 7

逆推序列:badc(1010)

原序列:bcad

x = 8

逆推序列:bcad(1100)

原序列:bcda

x = 9

逆推序列:bcda(1110)

原序列:bdac

x = 10

逆推序列:bdac(1200)

原序列:bdca

x = 11

逆推序列:bdca(1210)

原序列:cabd

x = 12

逆推序列:cabd(2000)

原序列:cadb

x = 13

逆推序列:cadb(2010)

原序列:cbad

x = 14

逆推序列:cbad(2100)

原序列:cbda

x = 15

逆推序列:cbda(2110)

原序列:cdab

x = 16

逆推序列:cdab(2200)

原序列:cdba

x = 17

逆推序列:cdba(2210)

原序列:dabc

x = 18

逆推序列:dabc(3000)

原序列:dacb

x = 19

逆推序列:dacb(3010)

原序列:dbac

x = 20

逆推序列:dbac(3100)

原序列:dbca

x = 21

逆推序列:dbca(3110)

原序列:dcab

x = 22

逆推序列:dcab(3200)

原序列:dcba

x = 23

逆推序列:dcba(3210)

process returned 0 (0x0) execution time : 3.452 s

press any key to continue.

小結:

康拓展開,可為a*演算法服務;

康托展開與康托展開的逆運算

康托展開用來求陣列是該全排列的第幾項,康托展開的逆運用用於求全排列的第幾個排列。已知對於1 n個數的全排列,總共的可能是n 種。對於乙個已知的數列比如45321,在第一項是4時,表示第一項在此之前已經填放過1 2 3了,而後面的第二項至第五項則又是乙個全排列,那麼此時的排列數就是3 4 第二位是5,...

康拓展開及其逆運算和全排列函式

有所摘抄,但重要的是自己的想法。康托展開是乙個全排列到乙個自然數的雙射,常用於構建雜湊表時的空間壓縮。康托展開的實質是計算當前排列在所有由小到大全排列中的順序,因此是可逆的。x a n n 1 a n 1 n 2 a i i 1 a 1 0 index 1 2 n i 1 n 其中,a i 為整數,...

康托展開及其逆運算

康托展開的wiki介紹 申明 1.用c語言實現。2.for中的i,j定義適用於c99標準,gcc編譯要新增 std c99選項。或者將i,j的定義放到for之前的外部作用域。3.逆運算使用了c99標準的vla,即變長陣列,只能用於區域性作用域,且宣告時不能初始化 也可以不用vla,使用malloc等...