一共有三种求全排列的方式:
第一种就是只适合用于非可重集的DFS实现
第二种就是可以用于可重集上的刘汝佳书上的代码
第三种就是STL中的next——permutation
在对这三种方式做了比较之后发现:
DFS实现的效率最高,当n = 10的时候耗时才不到2s,但是n = 11的时候耗时14s
这是因为在求排列的时候DFS没有去判断这个元素在集合中是否重复的出现过,只是直接的去判断vis数组
第二种方式刘汝佳的实现方式,效率比较的低,甚至不如STL中的next——permuation函数,但是我猜想STL中的实现方式和刘汝佳的差不多
第三种方式使用的时候必须要先把所要求全排列的集合进行排序。
综上所述:
以后遇到求全排列的时候,如果是非可重集,那么使用DFS(实际上还是一个递归的过程,即分治,结合)
如果是可重集,那么直接使用STL
下面附上第一种和第三种的代码
//STL实现方式 #include#include #include #include using namespace std;const int maxn1 = 100 + 10; int A1[maxn1]; int main() {for(int i = 1;i <= 10;i++){A1[i] = i;}do{for(int i = 1;i <= 20;i++){printf("%d ",A1[i]);}printf(" ");}while(next_permutation(A1 + 1,A1 + 1 + 10));printf("%lf",(double)clock()/CLOCKS_PER_SEC);return 0; }
//有的人把这种实现方式称作DFS的方式? //但是DFS虽然是递归实现的,但是它在决定下一次递归的时候是考虑和当前点的关系的 //所以我更倾向于称这种方式为递归实现的方式 //但是里面还是有很多图论中的味道的。 #include#include #include using namespace std;const int maxn = 100 + 10; int ans[maxn]; int vis[maxn]; int A2[maxn]; void print_permutation1(int cur ,int n) {if(cur > n){for(int i = 1; i <= n;i++){printf("%d ",ans[i]);}printf(" ");}else for(int i = 1; i <= n;i++){if(!vis[i]){vis[i] = 1;ans[cur] = A2[i];print_permutation1(cur + 1,n);vis[i] = 0;}} }int main() {for(int i = 1;i <= 11;i++){A2[i] = i;}memset(vis,0,sizeof(vis));print_permutation1(1,11);printf("%lf",(double)clock()/CLOCKS_PER_SEC);return 0; }