全排列問題演算法及實現(Permutation)

2021-07-25 12:02:10 字數 2366 閱讀 5293

做專案遇到資料採集系統中adc拼合問題,如果順序不對,波形就是錯誤的(題外話),為了找到正確的順序,涉及到排列問題。

一般地,從n個不同元素中取出m(m≤n)個元素,按照一定的順序排成一列,叫做從n個元素中取出m個元素的乙個排列(arrangement)。特別地,當m=n時,這個排列被稱作全排列(permutation)。 

ex:考慮三個數字1,2,3,這個序列有6個可能的排列組合 

123 

132 

213 

231 

312 

321 

這些排列組合根據less-than操作符做字典順序的排序。 

字典順序顧名思義是就是將1-n的乙個排列看成乙個數,然後按照字典的順序從小到達的輸出

所謂的全排列,就是說將數字進行不重複的排列,所有得到的序列,就是全排列 

給定數字1 , 2 , 3 , 4,其全排列是: 

, , , , ,

, , , , ,

, , , , ,

, , , , ,  

全排列如上所示,那麼什麼是全排列的序號?這裡我們通常將全排列按照字典序進行編排,就如上面從左到右看,就是按照字典序排列的。 

我們說,對於1,2,3,4的全排列,第20號序列是,因為其在這個按照字典序排列的全排列中處在第20的位置。

在stl中,有next_permutation的演算法實現。 

next_permutation()會取得[first,last) 所標之序列的下乙個排列組合。如果沒有下乙個排列組合,便返回false,否則返回true。 

演算法: 

首先,從最尾端開始往前尋找兩個相鄰元素,令第乙個元素為*i,第二個元素為*ii,且滿足*i < *ii。找到這樣一組相鄰元素後,再從最尾端開始往前檢驗,找出第乙個大於*i 的元素,令為*j ,將i,j元素對調,再將ii之後的所有元素顛倒排序。 

如下圖:方框為i和ii 

};首先,從最尾端開始往前尋找兩個相鄰元素,令第乙個元素為*i,第二個元素為*ii,且滿足*i > *ii。找到這樣一組相鄰元素後,再從最尾端開始往前檢驗,找出第乙個小於*i 的元素,令為*j ,將i,j元素對調,再將ii之後的所有元素顛倒排序。 

**和next_permutation類似

康托展開式實現了由1到n組成的全排列序列到其編號之間的一種對映 

公式: 

x=an*(n-1)!+an-1*(n-2)!+…+ai*(i-1)!+…+a2*1!+a1*0!

由1到n這n個數組成的全排列,共n!個,按每個全排列組成的數從小到大進行排列,並對每個序列進行編號(從0開始),並記為x;比如說1到4組成的全排列中,1234對應編號0,1243對應編號1。

對於ai(係數)的解釋需要用例子來說明:

對1到4的全排列中,我們來考察3214,則

a4==2

a3==1

a2==0

a1=0(最後只剩下一項)

也就是說康托公式中的每一項依次對應全排列序列中的每個元素,並按上述規則對映;

則x=2*3!+1*2!+0*1!+0*0!=14,即3214對應的編號為14。

code:

//已知排列求序號

long

long getindex(short dim, short *rankbuf)

康托公式可以根據排列的序號來求出該排列,即通過x的值求出ai(i大於等於1小於等於n)的值,運用輾轉相除的方法即可實現,現在已知乙個編號14(注意該編號是從0開始的,如果是從1開始,此處要減1),求其對應的全排列序列: 

14 / (3!) = 2 餘 2 

2 / (2!) = 1 餘 0 

0 / (1!) = 0 餘 0 

0 / (0!) = 0 餘 0 

故得到:a4=2,a3=1,a2=0,a1=0,由ai的定義即可確定14對應的全排列為2103.

code:

//已知序號求排列

void getpermutation(int dim, short *rankbuf, long

long

index)

for (i = dim - 1; i; i--)

for (j = i - 1; j >= 0; j--)

if (rankbuf[j] <= rankbuf[i])

rankbuf[i]++; //根據逆序數陣列進行調整

}

全排列演算法及實現

全排列在很多程式都有應用,是乙個很常見的演算法,常規的演算法是一種遞迴的演算法,這種演算法的得到基於以下的分析思路。給定乙個具有n個元素的集合 n 1 要求輸出這個集合中元素的所有可能的排列。一 遞迴實現 例如,如果集合是,那麼這個集合中元素的所有排列是,顯然,給定n個元素共有n 種不同的排列,如果...

全排列演算法及實現

全排列在很多程式都有應用,是乙個很常見的演算法,常規的演算法是一種遞迴的演算法,這種演算法的得到基於以下的分析思路。給定乙個具有n個元素的集合 n 1 要求輸出這個集合中元素的所有可能的排列。一 遞迴實現 例如,如果集合是,那麼這個集合中元素的所有排列是,顯然,給定n個元素共有n 種不同的排列,如果...

全排列演算法及實現

全排列在很多程式都有應用,是乙個很常見的演算法,常規的演算法是一種遞迴的演算法,這種演算法的得到基於以下的分析思路。給定乙個具有n個元素的集合 n 1 要求輸出這個集合中元素的所有可能的排列。一 遞迴實現 例如,如果集合是,那麼這個集合中元素的所有排列是,顯然,給定n個元素共有n 種不同的排列,如果...