從n個不同元素中取出n個元素的排列,稱為n個不同元素的全排列。
可以證明,n個元素的全排列的總數是n!。
全排列的生成演算法就是對於給定的元素集合,用有效的方法將所有可能的全排列無重複無遺漏地列舉出來。
n個不同元素的排列都可以與n個自然數1、2
、……,n的排列一一對應,所以,這裡就以n個數字的排列為例說明排列的生成演算法。全排列的生成演算法就是討論怎樣從乙個排列生成它乙個新的排列的方法。
1.字典序演算法
不同的排列,可以從左到右逐個比較對應的元素的順序來決定他們的先後順序。設有集合的兩個排列 a0a1 ……aj……an-1和 b1b2……bj……bn-1bn,從左端開始,逐個比較它們的對應元素的大小,如果出現對應數字不相同的第乙個位置為 j,並且aj<bj,則a0a1 ……aj……an-1就排在b0b1……bj……bn-1的前面。例如對於5
個數字的排列
12354
和12345
,兩個排列的前三個數字相同,出現不同數字的位置是 j=3,而排列
12354
的第四個數字
5在排列
12345
的第四個數字
4之後,所以排列
12345
在前,排列
12354
在後。根據這樣的規定,
5個數字的所有的排列中,第乙個排列是
12345
,最後乙個是
54321
。這種判斷排列順序的方法稱為字典序法。
根據字典序法生成所有全排列的演算法如下:
設p是集合的乙個全排列:p=p1p2……pj-1pjpj+1……pn(1
≤p1、 p2、……、pn≤n-1)
第一步:從排列的右端開始,找出第乙個比右邊數字小的數字的序號j,即j=max
第二步:在pj 的右邊的數字中,找出所有比pj 大的數字中最小的數字pk,即k=min
第三步:交換pi,pk
第四步:再將排列右端的遞減部分pj+1pj+2……pn倒轉,就得到了乙個新的排列p'=p1p2……pj-1pjpn……kpj+2pj+1。
例如839647521
是數字1~9
自右至左找出排列中第乙個比右邊數字小的數字4 839647521
在該數字後的數字中找出比4
大的數中最小的乙個
5 839647521將5與
4交換
839657421
將7421
倒轉
839651247
所以839647521
的下乙個排列是
839651247。
為了得到集合的全體全全排列,可以從原始排列
12……n開始,按照字典序法逐個生成它們的後繼排列。當得到的後繼排列是最後乙個n……21
時就結束。
字典序演算法的程式**:
//字典序演算法
//輸入:排列元素個數n
//輸出:
n個元素的排列
#include
#include
using namespace std;
void dict(int *p,int n);
void output(int *p,int n);
int t;
int main(void)
freopen("in.dat","r",stdin);
int n,*p;
while(cin>>n)
p=new int[n];
for(int i=0;ip[i]=i+1;
t=0;
dict(p,n);
return 0;
void dict(int *p,int n)
int i,j;
while(1)
output(p,n);
for(i=n-2;i>=0;i--)
if(p[i]break;
if(i<0)
break;
for(j=n-1;j>=0;j--)
if(p[j]>p[i])
break;
swap(p[i],p[j]);
j=n-1;
while(iswap(p[++i],p[j--]);
void output(int *p,int n)
cout 在資料結構中,所謂的字典序列其實很簡單 就是元素根據英文本母的順序排列,就叫字典序列 比列就是乙個字典序列 對於集合在資料結構中我們用std set來管理和使用它,需要注意的是集合中不能有相同元素,就和高數一樣的。所以std set中的元素必須有 比如像這樣的乙個集合,排列順序的話有4 3 2 1 ... 問題描述 在資料加密和資料壓縮中常需要對特殊的字串進行編碼。給定的字母表a由26 個小寫英文本母組成a 該字母表產生的公升序字串是指字串中字母按照從左到右出現的次序與字母在字母表中出現的次序相同,且每個字元最多出現1次。例如,a,b,ab,bc,xyz 等字串都是公升序字串。現在對字母表a 產生的所... 之前在中描述了全排列演算法的遞迴解法,這裡再說一種演算法 字典序排列。字典序排列就是按照字典a z,1 9的順序給出字串的順序全排列,例如abc的全排列就是從abc一直排到cba。那麼給定乙個字串,怎麼找出恰好大於該字串的下乙個排列呢?我們考慮如下的步驟 1 假設字串為p1p2 pn,我們從後往前尋...c STL演算法與應用 一 字典序列與全排列
演算法筆記 01 字典序問題
全排列演算法的字典序排列