a)求一个全排列函数:如p([1,2,3]) ,输出: [123],[132],[213],[231],[321],[312]。
b)求一个组合函数: 如p([1,2,3]) ,输出:[1],[2],[3],[1,2],[2,3],[1,3],[1,2,3]。
全排列和组合都可以用递归实现,全排列也可以用stl算法实现。
全排列:
第一问可以直接用stl里面的bool next_permutation(beg, end),该函数会给出下一个排列。下面是stl里next_permutation(beg, end)函数模板实现,具体算法参考《STL源码剖析》
template <class _BidirectionalIter>
bool next_permutation(_BidirectionalIter __first, _BidirectionalIter __last) {
__STL_REQUIRES(_BidirectionalIter, _BidirectionalIterator);
__STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type,
_LessThanComparable);
if (__first == __last)
return false;
_BidirectionalIter __i = __first;
++__i;
if (__i == __last)
return false;
__i = __last;
--__i;
for(;;) {
_BidirectionalIter __ii = __i;
--__i;
if (*__i < *__ii) {
_BidirectionalIter __j = __last;
while (!(*__i < *--__j))
{}
iter_swap(__i, __j);
reverse(__ii, __last);
return true;
}
if (__i == __first) {
reverse(__first, __last);
return false;
}
}
}
/**************************************
Author : Pegasus
Time :5/7/2014 6:47:52 PM
FileName:perm_stl.cpp
Desc :
*************************************/
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
void print(int *a, int n) {
for (int i = 0; i < n; ++i)
printf("%d ", a[i]);
printf("\n");
}
int main()
{
const int n = 3;
int a[n] = {1, 2, 3};
do {
print(a, n);
} while (next_permutation(a, a+n));
return 0;
}
当然不会让你用stl的,上面只是作为例子学学stl怎么实现的。
递归实现;注意由于递归顺序,这种方法与上一种输出并不完全相同,不是严格按照字典序输出的。递归最后输出的是312而不是321
#include <iostream>
#include <cstdio>
#include <algorithm> //for swap
using namespace std;
int n;
void print(int *a, int n) {
for (int i = 0; i < n; ++i)
printf("%d ", a[i]);
printf("\n");
}
void perm(int *a, int cur) {
if (cur == n-1) {
print(a, n);
return;
}
for (int i = cur; i < n; ++i) {
swap(a[i], a[cur]);
perm(a, cur + 1); //将数组所有数分别与第一个交换,这样就总是处理后n-1个数的全排列
swap(a[i], a[cur]); //恢复现场
}
}
int main()
{
n = 3;
int a[3] = {1, 2, 3};
perm(a, 0);
return 0;
}
组合问题最简单的方法是枚举,但是当数组比较大的时候就不好枚举了,还是用递归。
设函数comb(int m, int k),当第一个数字选定后,其后的数字是从余下的m-1个数中选取k-1个数字的组合,找到这个递归关系就行了。
/**************************************
Author : Pegasus
Time :5/7/2014 6:59:41 PM
FileName:comb.cpp
Desc :
*************************************/
#include <iostream>
#include <cstdio>
using namespace std;
int a[10];
int n;
void comb(int m, int k) {
for (int i = m; i >= k; --i) {
a[k] = i;
if (k > 1) {
comb(i-1, k-1);
} else {
for (int j = 1; j <= n; ++j)
if (a[j] != 0)
printf("%d", a[j]);
printf("\n");
}
}
}
int main()
{
n = 3;
for (int i = 1; i <= 3; ++i)
comb(3, i);
return 0;
}
以前写过类似的:
http://blog.csdn.net/pegasuswang_/article/details/9131653