全排列的定義見全排列.
這里我們詳細講一下交換法和字典序法
交換法
舉個簡單的例子,假設(shè)我們要對1234進行全排列
1.首先保證1不變,對234進行全排列
同樣的,對234進行全排列可以保證2不變,對34進行全排列,然后保證3不變,對4進行全排列,因為4只有一個數(shù),所以全排列只有一種,然后我們就得到了
1234
1243
1324
1342
1423
1243
2.這樣我們就得到了以1開頭的所有全排列,接下來就是得到分別以2,3,4開頭的全排列了
只要我們將1與2,3,4分別交換,就分別得到了以2,3,4開頭的初始序列。
代碼
#include<iostream>
using namespace std;
int arr[5]={0,1,2,3,4};
void swap(int x,int y)//用于交換數(shù)組的兩個數(shù)
{
int temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
int resove(int n)//遞歸函數(shù)
{
if(n==5)//當嘗試對不存在的數(shù)組元素進行遞歸時,標明所有數(shù)已經(jīng)排列完成,輸出。
{
for(int i=0;i<5;i++)
cout<<arr[i];
cout<<endl;
return 0;
}
for(int i=n;i<5;i++)//循環(huán)實現(xiàn)交換和之后的全排列
{//i是從n開始 i=n;swap(n,i)相當于固定當前位置,在進行下一位的排列。
swap(n,i);
resove(n+1);
swap(n,i);
}
}
int main()
{
resove(0);
}
如果初始序列中有重復(fù)元素的話,只要去重就可以了
bool isSwap(int begin,int end)
{
for(int i=begin;i<end;i++)
{
if(arr[i]==arr[end])
return false;
return true;
}
}
然后在循環(huán)的時候加上這個條件就行了。
for(int i=n;i<5;i++)//循環(huán)實現(xiàn)交換和之后的全排列
{//i是從n開始 i=n;swap(n,i)相當于固定當前位置,在進行下一位的排列。
if(isSwap(n,i))
{
swap(n,i);
resove(n+1);
swap(n,i);
}
}
123的全排列
123
132
213
231
321
312
可能你已經(jīng)發(fā)現(xiàn)了,這樣的輸出是沒有順序的,如果我們要求輸出必須按照字典序輸出的話,這樣顯然是不可以的。所以接下來介紹一種字典序法。
字典序法
直接看代碼吧,我也不知道咋解釋
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 7;
char site[maxn] = {0};
string str;
void solve(int num)
{
if(num == str.length())
{
for(int i = 0; i < str.length(); ++i)
{
cout << site[i];
}
cout << endl;
}
else
{
int flag = 0; // 判斷是否出現(xiàn)過
char tmp;
for(int i = 0; i < str.length(); ++i)
{
// 判斷是否出現(xiàn)過
tmp = str[i];
flag = 0;
for(int j = 0; j < num; ++j)
{
if(site[j] == tmp)
{
flag = 1;
break;
}
}
if(flag == 1) continue;
site[num] = str[i];
solve(num+1);
}
}
}
int main()
{
int count = 0;
while(cin >> str)
{
sort(str.begin(), str.end()); // 按字典序輸出
solve(0);
cout << endl;
}
return 0;
}
注意,字典序法要求輸入的也是一個有序列。
今天在推薦一首歌,過客, 挺好聽的