题目:
算法竞赛入门经典例7-2-1:输入整数n,按字典序从小到大的顺序输出前n个数的 所有排列
A:已确定的前缀数列
S:需要进行全排列的元素集合
伪代码:
void print_permutation(序列A, 集合S)
{ if(S为空) 输出序列A; else 按照从小到大的顺序依次考虑S的每个元素v { print_permutation(在A的末尾填加v后得到的新序列, S-{v}); }
}
分析一下伪代码啊,第一次for循环从一开始,然后进行不断的递归,递归时遇见出现过的元素,就跳过,因此不断产生新的元素开头的全排列,比如第一次:A:1,S:2—9;递归->A :1,2,S:3—9
总体上是一个解答树:
从上到下一直到最底层,然后回溯,走到其他子层。
已经确定的前缀序列:用数组表示。
cur:当前需要确定的元素位置
S:不需要用数组保存,因为A中没出现的元素都可选,所以可由A来确定s
标志变量ok:检查元素是否用过
#include<iostream>
#include<cstdio>
using namespace std;
int a[1000];
void print_permutation(int n,int *a,int cur);
int main(){int n;cin>>n;print_permutation( n, a, 0);
}void print_permutation(int n,int *a,int cur){if(cur==n) {for(int i=0;i<n;++i) printf("%d ",a[i]);printf("\n") ;}else{for(int i=1;i<=n;++i){//改变前缀int ok = 1;for(int j=0;j<cur;++j){//如果i已经在A[0]~A[cur-1]出现过,则不能再选if(a[j]==i) ok = 0;}if(ok){a[cur]=i;print_permutation( n, a, cur + 1);//每一个前缀的可能排序}}}
}