如何产生全排列?

产生全排列的算法问题看似简单,实际也是一个经典的问题。以下给出了两种解法,一种是递归解法,另一种是STL模板库里面的产生下一个排列数的函数源代码。

 

方法一: 将产生N个数的全排列的问题看成先产生一个数的排列,再产生两个数的排列,当N=n时,递归出口,输出所求的排列。整个过程形成一颗递归树。

level为树的深度,最深为n,输出结果。每输出一个结果需要一个向量保存中间的排列。

                                           0

         10                                                      01

 210 120 102                              201 021 012

#include <iostream>
#include <vector>

using namespace std;

void gen(vector<int> & permutation, int level, int n) 

{
 int i;
 if(level==n)
 {
  for(i=0;i<n;i++)
   cout<<permutation[i];
  cout<<endl;
 }
 else
 {
  for(i=0;i<=level;i++)
  {
   vector<int>  p(permutation); 
   p.insert(p.begin()+i,level); 
   gen(p,level+1,n);
  }
 }
}

int main()
{
 int n;
 cin>>n;

 vector<int> permutation;
 gen(permutation,0,n);
 return 0;
}

 

方法二:使用STL里面的next_pemutation算法

该算法的思想是:

1234-》4321

排列按字典序生成结果。

每次根据给出的排列(First,...,Last),先找寻一个顺序对n,n1,然后将该顺序对左面的数n,与从右开始看,比该数小的那个数m交换;将n1与Last之间的数逆序。

 // next_permutation and prev_permutation, with and without an explicitly
  // supplied comparison function.

  /**
   *  @brief  Permute range into the next "dictionary" ordering.
   *  @param  first  Start of range.
   *  @param  last   End of range.
   *  @return  False if wrapped to first permutation, true otherwise.
   *
   *  Treats all permutations of the range as a set of "dictionary" sorted
   *  sequences.  Permutes the current sequence into the next one of this set.
   *  Returns true if there are more sequences to generate.  If the sequence
   *  is the largest of the set, the smallest is generated and false returned.
  */
  template<typename _BidirectionalIterator>
    bool
    next_permutation(_BidirectionalIterator __first,
       _BidirectionalIterator __last)
    {
      if (__first == __last)
 return false;
      _BidirectionalIterator __i = __first;
      ++__i;
      if (__i == __last)
 return false;
      __i = __last;
      --__i;

      for(;;)
 {
   _BidirectionalIterator __ii = __i;
   --__i;
   if (*__i < *__ii)
     {
       _BidirectionalIterator __j = __last;
       while (!(*__i < *--__j))
  {}
       std::iter_swap(__i, __j);
       std::reverse(__ii, __last);
       return true;
     }
   if (__i == __first)
     {
       std::reverse(__first, __last);
       return false;
     }
 }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值