您的位置:首页 > 其它

打印全排列

2014-01-06 10:15 106 查看
今天碰到一个打全排列的问题,仔细研究了一下,用递归的思想搞出来了,现在把大概思想贴在下面了:假设要打印的是a, b , c , d , e , 很明显应该采用递归,递归就得有子问题打印a, b , c , d , e 的问题可以分解成以下几个子问题打印a, 打印{b , c , d , e}的全排列打印b, 打印{a , c , d , e}的全排列打印c, 打印{a , b , d , e}的全排列打印d, 打印{a , b , c , e}的全排列打印e, 打印{a , b , c , d } 的全排列
这样就能确定函数的输入PrintPermutation (int a[ ], int len){ if (len==1) 终止操作 else { len个子问题,Printpermutation (a, len-1); }}
这里第一个要解决的问题是什么时候输出打印,如果把打印写在else里,由于递归的深度不同,就会产生排前面的数打印的次数少,排后面的数打印次数多,最保险的做法是,当len==1时,才打印整个排列,也即是写在终止操作里。 但是此时,len=1,并不确定原来一共有几个数,因此,在函数中加一个参数k, PrintPermutation (int a[], int k, int len), k是记录还有k个数要排,一直保持数组长度len的值不变是为了在打印排列的时候知道什么时候该终止。 (如果是打印字符串的全排列,可以省掉一个参数,因为字符串的结尾是确定的)
第二个问题是当长度为K时,子问题的数量是K个,如何写成一个循环的形式呢?最简单的思路是从i=1:K,依次把把a[i]与a[1]进行交换,然后对后面的K-1个数进行全排列,用程序实现就是 swap(a[1],a[i]) PrintPermutation(a, k-1, len)当i个子问题解决完后,还需要 swap(a[1],a[i])交换回来,再解决下一个子问题,不然,后面的次序就乱了。
理清思路写程序应该不难, swap(int &a, int &b) 这里需要加引用
void PintPermutation(int a[], int k, int len){ if (len<=0) return;
if (k==1) { for (int i=0; i<len; i++) cout<< a[i]<<' '; cout<<endl; } else { for (int i=0; i<k ; i++) { swap(a[len-k],a[len-k+i]); % 交换 PrintPermutation(a,k-1,len); swap(a[len-k],a[len-k+i]); } }}
对于上面的程序,主要在交换这一句swap(a[len-k],a[len-k+i]);
如果把K的含义改一下,看起来更容易一点PrintPermutation(a, k, len),如果k的含义是从a[k]到a[len-1]的排列,swap就换成swap(a[k],a[k+i]), 递归调用中K+1, 递归终止条件就变成 k==len-1。

上面只是提供了一个打印全排列的思想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: