前几天遇到一个组合的问题,在《编程之美2.3》上找到了解决方法。
昨天在看July的博客,看到了全排列的问题,结果状态不佳,写了好久没写出来。
今天看到了STL库中next_permutation的解法,理解完实现了一下。
递归版本:
优点 : 元素不必预先排序,并且允许出现相同项
缺点: 递归开销大
非递归版本(字典序排序):
优点:没有递归疯狂的函数调用(入栈,出栈),效率高
缺点:因为是字典序排序,不允许出现相同项,调用前必须先排序
/*
* ********************* 全排列的递归写法 ****************************************************
*/
#include <iostream>
using namespace std;
void AllPermutation(char *a,int i,int n)
{
/*
* 输出 a[0] ~ a[n-1] 的全排列
* i 为当前被固定的元素的序号
*/
// 1. 如果 i 为最后一个被固定的数,此时为一种排序,输出
if(i == n -1 )
{
for(int i = 0;i < n;++i)
cout << a[i] << " ";
cout << endl;
return;
}
// 2.如果 i 不是最后一个数,依次交换 i 与之后的项,进行一次全排列
for(int j = i;j < n;++j)
{
swap(a[j],a[i]);
AllPermutation(a,i + 1,n);
swap(a[j],a[i]);
}
}
int main()
{
char a[] = {'a','b','c'};
int n = sizeof(a)/sizeof(char);
AllPermutation(a,0,n);
}
/*
* *********************************全排列的非递归写法**************************************
*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template <class Iterator>
bool next_permutations(Iterator begin,Iterator end)
{
/*
* 找出序列的下一个序列
* 如 1234 -> 1243 -> 1324 ->1342 ->1423 > 1432
*/
Iterator first = begin;
Iterator last = end;
Iterator i;
Iterator ii;
Iterator j;
// 1.1 从后往前找出两个相邻的项,使得 i < ii
for(--last;last != begin;--last)
{
if(*(last - 1) < *last)
{
i = last - 1;
ii = last;
break;
}
}
// 1.2 如果找不到这样的项,结束
if(last == begin)
return false;
// 2.1 继续从后往前找到第一个大于i的项,标记为 j
for(last = end - 1;last != i; --last)
{
if(*last > *i)
{
j = last;
break;
}
}
// 2.2 如果找不到这样的项,结束
if(last == i)
return false;
// 3.1 交换 i 和 j 两个项
iter_swap(i,j);
// 3.2 从 ii 开始(包括 ii )逆转所有项
reverse(ii,end);
return true;
}
int main()
{
// 1. 构建一个序列
vector<char> vec;
vec.push_back('1');
vec.push_back('2');
vec.push_back('3');
vec.push_back('4');
// 2. 对序列进行排序
sort(vec.begin(),vec.end());
// 3. 输出初始序列
for(auto i = vec.begin();i != vec.end();++ i)
cout << *i << " ";
cout << endl;
// 4. 输出余下序列
while(next_permutations(vec.begin(),vec.end()))
{
for(auto i = vec.begin();i != vec.end();++ i)
cout << *i << " ";
cout << endl;
}
}
参考:
《STL源码剖析》
http://www.cnblogs.com/devymex/archive/2010/08/17/1801122.html