n个不同对象的排列组合一共有n!种。例如,1, 2, 3, 4这几个数可能的排列组合有1*2*3*4 = 24种。
1234, 1243, 1324, 1342, 1432, 1423
2134, 2143, 2314, 2341, 2431, 2413
3214, 3241, 3124, 3142, 3412, 3421
4231, 4213, 4321, 4312, 4132, 4123
递归函数最适合被用于计算排列组合,假设使用一个数组ary来表示需要排列的对象,数组索引idx的初始值为0,则计算其所有排列组合的算法perm思路如下。
把ary[idx]依次与ary[idy] (idy >= idx)交换,每次交换完之后,idx自加1,并且作为参数,递归调用函数perm。
算法的C++源代码如下(在ubantu上面用gcc编译,可以成功执行)。
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <sys/time.h>
using namespace std;
int len, sum;
void perm(int *ary, int pos){
int i, tmp;
if(pos == len - 1){
sum++;
for(i = 0; i < len; i++){
cout<<ary[i];
}
cout<<endl;
return;
}
for(i = pos; i < len; i++){
tmp = ary[pos];
ary[pos] = ary[i];
ary[i] = tmp;
perm(ary, pos + 1);
ary[i] = ary[pos];
ary[pos] = tmp;
}
}
int main(int argc, char **argv){
ifstream fin("./input.txt");
int *array, idx;
if(argc < 2){
cout<<"Input the number of integers to be permutated!"<<endl;
return 0;
}
if(!fin.is_open()){
cout<<"Cannot open file ./input.txt!"<<endl;
return 0;
}
len = atoi(argv[1]);
array = new int[len];
idx = 0;
while(!fin.eof() && idx < len){
fin>>array[idx];
idx++;
}
sum = 0;
struct timeval start, end;
double timeuse;
gettimeofday(&start, NULL);
perm(array, 0);
gettimeofday(&end, NULL);
timeuse = 1000000*(end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
timeuse/=1000000;
cout<<"time used: "<<timeuse<<", total num: "<<sum<<endl;
delete array;
return 0;
}