全排列问题基本都可以转化成对1~n的数字的全排列,所以本文只讨论1~n的全排列问题。
题目:1~n的全排列
思想:
- 用数组记录操作后的序列,输出结果时只需要输出该数组即可;
- 交换第1个元素与第i(1=<i<=n)个元素,得到n个序列;把每个序列分成两部分:第一个元素,其余的元素;对其余元素执行全排列操作;(记得操作完后,将这两个元素交换回来,以方便下面的交换)
- 当剩余序列中只有一个元素时,得到一种排列结果,输出该结果
猜想结果:
1~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
三思:
- 该算法怎么不是按顺序排列?因为算法本身特点,只是在大框架下保证顺序输出【记以1开头的6个,接着是以2开头的,接着以3开头的序列(首个为3214),……】;由于1234因调换<1-3>就出现了3214且以其作为3序列的开头,而3124比它小,却只能排在它后面。
- 给算做的调换都是有效调换,时间主要耗在函数调用上。(其实更耗时间的该是打印结果)
- 如果数组有重复怎么办?,例:求“1223”的全部排列?
代码:
1 #include <iostream>
2 using namespace std;
3 const int MaxNum=9;
4 int iArr[MaxNum];//定义数组
5 int count;//定义计数器
6 inline void Swap(int *a,int *b)//交换两个位置的值
7 {
8 int temp;
9 temp=*a;
10 *a=*b;
11 *b=temp;
12 }
13 int FullArray(int k,int m)//对下标为k~m的数进行全排列
14 {
15 int i=0;
16 if(k==m){
17 for(i=0;i<=m;i++){//用输出数组值的方法,使问题得到简化;回避了好些问题,如果把值一个个输出问题就复杂了
18 cout<<iArr[i];//由于设置MaxNum=9;当MaxNum设置超过9时记得改为cout<<iArr[i]<<" ";
19 }
20 cout<<endl;
21 count++;
22 return 1;
23 }
24 for(i=k;i<=m;i++){//第一次是无效替换——Swap(&iArr[k],&iArr[k]);这是个技巧
25 Swap(&iArr[k],&iArr[i]);
26 FullArray(k+1,m);
27 Swap(&iArr[i],&iArr[k]);
28 }
29 return 1;
30
31 }
32 void main()
33 { //此程序只对1~n进行全排列;
34 //如果需要对给定int数组进行全排列,则需修改iArr[MaxNum]的赋值;
35 //如果需要对给定char数组进行全排列,则可以把iArr[MaxNum]的值当下标使用;
36 int n,i;
37 for(i=0;i<MaxNum;i++)iArr[i]=i+1;//初始化数组,其存储的值依次为1,2,3,……
38 while(1){
39 system("cls");
40 count=0;//测试新用例时,count重新置0
41 cout<<"请输入n(最大为9):";
42 cin>>n;
43 if(n>MaxNum || n<1){cout<<"Error: n的值在设定值范围之外"<<endl;break;}
44 FullArray(0,n-1);
45 cout<<"1~"<<n<<"的全排列的个数:"<<count<<endl;
46 system("pause");
47 }
48 }
参考:http://plutoblog.iteye.com/blog/976216