打印全排列

本文详细解析了使用递归思想解决全排列问题的方法。通过分解子问题并利用交换技巧来实现,确保了所有可能的排列都能被正确生成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天碰到一个打全排列的问题,仔细研究了一下,用递归的思想搞出来了,现在把大概思想贴在下面了:
假设要打印的是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。


上面只是提供了一个打印全排列的思想。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值