全排列
一.问题描述
给定一组字符串,输出其全排列。比如,给定abc,其全排列为abc,acb,bac,bca,cab,cba。
二.思路
其实求全排列的过程可以看作一棵树。比如上面的求abc的全排列,它的全排列无非是以a或者b或者c开头,那么我们就分别以a,b,c为根节点建立一棵树。先遍历第一棵树,即以a为根节点的树,当前树的深度为1,小于三,说明以a为根的全排列还没有完成,则往下遍历,产生三个子节点即a,b,c。其中a我们已经用过了,那么只能用b或者c当作全排列的第二个字符。如果我们选择了b,那么当前的深度为2,仍小于3,那么我们就要继续往下遍历,b产生三个子节点即a,b,c,其中a,b均使用过,所以只能选择c。此时深度为3,说明这个从根到叶子的路径是一种全排列,则输出即为abc。输出之后应该回溯到上一层,刚才我们选择的是b,这次就应该选剩下的c。此时深度为2,小于3,所以向下遍历。注意回溯到上一层的时候,应该设置b为没有访问过。因为就算我们刚才用过了b然后又回溯到这,但是在遍历c的子节点是还可能用到b,所以应该设置b为没有访问过。c向下遍历产生三个子节点a,b,c,其中a,c已经使用过,所以只能选择b,而此时深度为3,则输出路径为acb。以此类推…
代码
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int MAXN = 10;
bool visit[MAXN]; //字符串内某个字母是否被遍历过
char sequence[MAXN]; //结果
//全排列可以用一个树表示,index就表示当前所处在第几层
void GetPermutation(string str,int index){
if(index == str.size()){
for(int i=0;i<str.size();i++){
printf("%c",sequence[i]);
}
printf("\n");
}else{
for(int i=0;i<str.size();i++){
if(visit[i] == true){
continue;
}
visit[i]=true;
sequence[index]=str[i];
GetPermutation(str,index+1);
visit[i]=false;
}
}
return;
}
int main()
{
string str;
while(cin>>str){
sort(str.begin(),str.end()); //将字符串按照字典顺序排序
GetPermutation(str,0);
printf("\n");
}
return 0;
}