紫书7.2.1 生成1-n的排列

输入正数n,按字典序从小到大的顺序输出n个数的所有排列。两个序列的字典序大小关系等价于从头开始第一个不相同位置处的大小关系。

递归的边界应该很好理解吧,当集合s[]中没有一个元素的时候,按照上面的伪码,s[]中的元素只能向序列a[]中跑,s[]没了元素,那么序列a[]就是一个完整的序列了。那么,直接输出序列a[]即可。按照从小到大的顺序考虑s[]中的每个元素,每次递归的调用以a[]开始。

如果伪码了解了,那么就得用代码实现了。很容易想到序列a[]用数组保存集合s[]中跑过来得数字,而s[]呢?如果要完成老师布置的第一个题目,那么s[]中的元素根本不要保存,因为s[]中的元素往a[]中跑,那么,跑过来得数字就间接的保存在了序列a[]中,只要没在序列a[]中出现过的数字都可以备选。由于C/C++传递数组的时候传递的是数组的首地址,所以,还需要传一个到底填了多少个数,也就是到底填到数组的第几个位置来了,我们把这个参数取名为cur
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <cstdio>
using namespace std;
int n;
int a[10000];
void per(int cur){
if(cur==n){
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
return ;
}
for(int i=1;i<=n;i++){
int flag=1;
for(int j=0;j<cur;j++){
if(a[j]==i) flag=0;
}
if(flag==1)
{
a[cur]=i;
per(cur+1);//!!!不能放在大括号后 只有满足当前位置填的数与之前不重复 才可以填下一个
}
}


}
int main(){
cin>>n;
per(0);
return 0;
}

image