全排列算法汇总(C++版)

全排列算法相信大家都比较熟悉了,这里只是对各种全排列算法进行一个汇总,让大家有个较全面的了解。由于有些版本被转载太多次了,故没法找到原创作者,这里就不特别注明了。

递归版本:

这是最通俗易懂的一个版本,不过网上流传的代码中第18行没有注释掉,我看了一下运行结果是一样的,只是顺序不一样。网上流传的版本在输出顺序上不是以递增的顺序出现,因为它每次交换过后又交换回来了。而注释掉的版本的输出顺序则是递增的顺序。
以下是代码:
  1. /**
  2. *   Permutation helper.
  3. *   @param  str     original strings
  4. *   @return         all the permutations
  5. */
  6. void Permutation_Generator(string str, int m, int n, vector<string> &result)
  7. {
  8.     if (m > n)
  9.     {
  10.         result.push_back(str);
  11.     }
  12.     else
  13.     {
  14.         for (int i = m; i <= n; ++i)
  15.         {
  16.             Swap<char>(str[m], str[i]);
  17.             Permutation_Generator(str, m + 1, n, result);
  18.             //Swap<char>(str[m], str[i]);
  19.         }
  20.     }
  21. }

  22. /**
  23. *   Get the permutation of the strings.
  24. *   @param  str     original strings
  25. *   @return         all the permutations
  26. */
  27. vector<string> Permutation(string str)
  28. {
  29.     vector<string> result;
  30.     Permutation_Generator(str, 0, str.size() - 1, result);
  31.     return result;
  32. }


非递归版本:
这个不是从网上看到的,是根据Kenneth H.Rosen的《离散数学及其应用的思路》写出来的。写得比较粗糙,还请见谅。

这个方法的主要思路是,根据当前序列确定下一个序列,直到某一条件被满足则所有序列遍历完成。

设一个序列为 {a 1,a 2, ... a n}。我们的目的是要找到下一个排列。
1.我们要找到a j和a j+1,使得a j<a j+1且a j+1>a j+2>...>a n。即找到两个元素,这两个元素后面的元素呈单减。
2.从a j+1开始,找到比a j大的最小的数a k,交换a j和a k
3.对j位置之后的数进行升序排序,生成的序列便是下一个排列。
  1. /**
  2.  *  Get the permutation of the vectors.
  3.  *  @param  vec     the vector that contains the elements
  4.  *  @return the output of all the permutation sequence
  5.  */
  6. template <typename T>
  7. vector<vector<T>> Permutation(vector<T> vec)
  8. {
  9.     vector<vector<T>> retPerm;
  10.     retPerm.push_back(vec);
  11.     bool ret = true;
  12.     while(true == ret)
  13.     {
  14.         ret = Next_Permutation(vec);
  15.         if (ret)
  16.         {
  17.             retPerm.push_back(vec);
  18.         }
  19.     }
  20.     return retPerm;
  21. }
  22. /**
  23.  *  Get the next permutation sequence according to the current sequence.
  24.  *  @param  vec     current sequenece
  25.  *  @return whether there exist next sequence
  26.  */
  27. template <typename T>
  28. bool Next_Permutation(vector<T> &vec)
  29. {
  30.     int i = vec.size() - 2;
  31.     //  find the position that vec[i] <= vec[i]
  32.     while (i > 0 && vec[i] > vec[i + 1])
  33.     {
  34.         --i;
  35.     }
  36.     //  find the least larger element located on the right side of vec[i]
  37.     int k = vec.size() - 1;
  38.     int leastLarger = -1;
  39.     for (int j = i; j < vec.size(); ++j)
  40.     {
  41.         if (vec[j] > vec[i])
  42.         {
  43.             leastLarger = j;
  44.             break;
  45.         }
  46.     }
  47.     if (leastLarger == -1)
  48.     {
  49.         return false;
  50.     }
  51.     while (k > i)
  52.     {
  53.         if ((vec[leastLarger] >= vec[k]) && (vec[k] > vec[i]))
  54.         {
  55.             leastLarger = k;
  56.         }
  57.         --k;
  58.     }
  59.     Swap(vec[i], vec[leastLarger]);
  60.     //  sort the remain part of vector
  61.     vector<T>::iterator it = vec.begin();
  62.     for (int j = 0; j < i; ++j)
  63.     {
  64.         ++it;
  65.     }
  66.     ++it;
  67.     sort(it, vec.end());
  68.     return true;
  69. }

以上便是最常用的两种方式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值