C语言全排列问题
题目描述
给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于小写字母有‘a’ <‘b’ < … <‘y’<‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。
输入
只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。
输出
输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:
已知S=s1,s2…sk,T=t1,t2…tk,则S<T等价于,存在p(1≤p≤k),使得s1=t1,s2=t2,…,sp−1=tp−1,sp<tp成立。
样例输入
abc
样例输出
abc
acb
bac
bca
cab
cba
解题思路:
要对字母进行全排列,采用的思路是,每一个位置要遍历排列的所有字母,如果这个字母满足条件,就选定这个字母放在这个位置。
这个条件有两种情况:
①第一个位置的条件只需满足这个字母之前未被第一个位置选定过;
②其他位置(指代第二个位置,第三个位置,第四个位置·····第N个位置)满足的条件是这个字母在该次排序中未被该位置前面的其他位置选定,当然当其他位置的前面位置已经选定字母时,这时其他位置可看做是第一个位置,即也要满足第①个条件(例如给定一个abcd的字符串,假设第一个位置已经固定为b,后面就是acd排序,此时第二个位置也就是后面第二三四中的第一个位置);
实现方法:
str[]为原数组。temp[]用来输出全排列的每一个结果。Int型数组flag[]用来记录str[]数组中字母的状态(选定了,str[i]的flag[i]=1,未被选定,其flag[i]=0)。当一个位置要选定一个字母时,如果要被选定的字母flag[i]=0时,被选定后,它相应的flag[i]值由0变为1。对于整个过程的实现,用函数dfs(step),step的值标志着状态(step从0开始)——处于第几个位置的字母选定中。在进行完第step个位置的选定后,再次进行step+1位置的选定,即在dfs(step)中调用dfs(step+1),这样满足了递归自身调用自身。该递归的出口为当step==len(数组的长度时),就令temp[step]=0,后输出temp数组,即得到一个结果。每次dfs(step)中调用完dfs(step+1),后使str[i]的flag[i]=0,即str[i]又成了未被排序的状态中。每个位置遍历所有字母则靠dfs(step)函数中的for循环来控制。
流程图:
代码:
#include<stdio.h>
#include<string.h>
char str[10],temp[10];//tmpt用来输出全排列的每一个结果
int len;
int flag[10]; //用来判断str中的第i个位置字符是否进行了此次排列
void dfs(int step){//当step=0,执行的dfs(0),选定了tmpt第一位字母,执行dfs(1),选定tmpt第二位字母,以此类推
if(step==len){ //只要执行的是dfs(step),tmpt的第step+1位的字母就被选定
temp[step]='\0';
printf("%s\n",temp);
}
for(int i=0;i<len;i++){
if(flag[i]==0){
flag[i]=1;
temp[step]=str[i]; //tmpt[step]的值由i和 flag[i]共同决定
dfs(step+1);
flag[i]=0; //每一次dfs(step+1)调用完成后flag[i]被置为0,str[i]又回到了未被排序的状态
}
}
}
int main(){
while(scanf("%s",str)!=EOF){
len=strlen(str);
dfs(0);
}
return 0;
}
这里我画了整个递归过程的一部分,之前一直没想明白怎么递归的。
希望有点帮助。。。