给定一个字符串,要求输出它的全排列,比如ABC,要求输出ABC、ACB、BCA、BAC、CBA、CAB。
对于这个题目很自然想到一次确定第一个元素然后找出所有情况,就像上例中先确定A**然后找出ABC和ACB。事实上在确定了A后剩下的BC其实也是一个字符串全排列问题,这时候递归就派上用场了,这是一道可以很好地检验自己到底有没有理解递归的题目。在递归的过程中有一个细节值得注意一下,当我们交换某一个元素新得到一个头部字符(比如交换上例中的A、B使字符B为头部节点),再递归剩下的字符串(A、C),完了之后必须将先前交换的元素再重新换回来(再次交换A和B),否则可能会输出重复的字符串(因为在递归时会将所有的字符串打乱,这时候有可能会以已在出现头部出现过的字符为头部)读者可以自己敲代码体会一下,这里就不作图说明了。
下面是参考代码,如有不足欢迎指正。
1 /************************************** 2 Author:Zhou You 3 Time:2014.09.14 4 **************************************/ 5 #include <cstdio> 6 #include <iostream> 7 8 using namespace std; 9 10 void OutputPermutation(string &strdata,unsigned ileft,unsigned iright) 11 { 12 if(ileft>iright) return; 13 14 if(ileft==iright){ 15 cout<<strdata<<endl; 16 return; 17 } 18 19 for(unsigned i=ileft;i<=iright;++i){ 20 swap(strdata[i],strdata[ileft]); 21 OutputPermutation(strdata,ileft+1,iright); 22 swap(strdata[ileft],strdata[i]); 23 } 24 } 25 26 void Solve() 27 { 28 string strdata; 29 cin>>strdata; 30 OutputPermutation(strdata,0,strdata.length()-1); 31 } 32 33 int main() 34 { 35 freopen("txt.in","r",stdin); 36 freopen("txt.out","w",stdout); 37 38 unsigned case_num= 0; 39 cin>>case_num; 40 41 for(unsigned i=0;i<case_num;++i){ 42 Solve(); 43 } 44 45 return 0; 46 }
txt.in文件case
3 a ab abc
txt.out输出结果
a ab ba abc acb bac bca cba cab