全排列算法相信大家都比较熟悉了,这里只是对各种全排列算法进行一个汇总,让大家有个较全面的了解。由于有些版本被转载太多次了,故没法找到原创作者,这里就不特别注明了。
递归版本:
这是最通俗易懂的一个版本,不过网上流传的代码中第18行没有注释掉,我看了一下运行结果是一样的,只是顺序不一样。网上流传的版本在输出顺序上不是以递增的顺序出现,因为它每次交换过后又交换回来了。而注释掉的版本的输出顺序则是递增的顺序。
以下是代码:
非递归版本:
这个不是从网上看到的,是根据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位置之后的数进行升序排序,生成的序列便是下一个排列。
以上便是最常用的两种方式。
递归版本:
这是最通俗易懂的一个版本,不过网上流传的代码中第18行没有注释掉,我看了一下运行结果是一样的,只是顺序不一样。网上流传的版本在输出顺序上不是以递增的顺序出现,因为它每次交换过后又交换回来了。而注释掉的版本的输出顺序则是递增的顺序。
以下是代码:
- /**
- * Permutation helper.
- * @param str original strings
- * @return all the permutations
- */
- void Permutation_Generator(string str, int m, int n, vector<string> &result)
- {
- if (m > n)
- {
- result.push_back(str);
- }
- else
- {
- for (int i = m; i <= n; ++i)
- {
- Swap<char>(str[m], str[i]);
- Permutation_Generator(str, m + 1, n, result);
- //Swap<char>(str[m], str[i]);
- }
- }
- }
- /**
- * Get the permutation of the strings.
- * @param str original strings
- * @return all the permutations
- */
- vector<string> Permutation(string str)
- {
- vector<string> result;
- Permutation_Generator(str, 0, str.size() - 1, result);
- return result;
- }
非递归版本:
这个不是从网上看到的,是根据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位置之后的数进行升序排序,生成的序列便是下一个排列。
- /**
- * Get the permutation of the vectors.
- * @param vec the vector that contains the elements
- * @return the output of all the permutation sequence
- */
- template <typename T>
- vector<vector<T>> Permutation(vector<T> vec)
- {
- vector<vector<T>> retPerm;
- retPerm.push_back(vec);
- bool ret = true;
- while(true == ret)
- {
- ret = Next_Permutation(vec);
- if (ret)
- {
- retPerm.push_back(vec);
- }
- }
- return retPerm;
- }
- /**
- * Get the next permutation sequence according to the current sequence.
- * @param vec current sequenece
- * @return whether there exist next sequence
- */
- template <typename T>
- bool Next_Permutation(vector<T> &vec)
- {
- int i = vec.size() - 2;
- // find the position that vec[i] <= vec[i]
- while (i > 0 && vec[i] > vec[i + 1])
- {
- --i;
- }
- // find the least larger element located on the right side of vec[i]
- int k = vec.size() - 1;
- int leastLarger = -1;
- for (int j = i; j < vec.size(); ++j)
- {
- if (vec[j] > vec[i])
- {
- leastLarger = j;
- break;
- }
- }
- if (leastLarger == -1)
- {
- return false;
- }
- while (k > i)
- {
- if ((vec[leastLarger] >= vec[k]) && (vec[k] > vec[i]))
- {
- leastLarger = k;
- }
- --k;
- }
- Swap(vec[i], vec[leastLarger]);
- // sort the remain part of vector
- vector<T>::iterator it = vec.begin();
- for (int j = 0; j < i; ++j)
- {
- ++it;
- }
- ++it;
- sort(it, vec.end());
- return true;
- }
以上便是最常用的两种方式。