标签:二次 问题 集合 n个元素 恢复 == oid print 设计
设R={r1,r2,...,rn}是要进行排列的n个元素,Ri=R-{ri}.集合X中元素的全排列记为Perm(X)。
(ri)Perm(X)表示在全排列Perm(X)的每一个排列前加前缀ri得到的排列。
R的全排列可以归纳定义如下:
1. 当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素;
2. 当n>1时,Perm(R)由(ri)Perm(R1),(r2)Perm(R2),...,(rn)Perm(Rn)构成。
由此递归定义,可设计产生Perm(R)的递归算法如下:(此处以int类型为例)
void Perm(int list[],int k,int m)
{//产生list[k;m]的所有排列
if(k ==m){//要排列的只有一个元素
for(int i=0;i<=m;i++) printf("%d",list[i]);
printf("\n");
else{
for(int j=k;i<=m;j++){
Swap(list[j],list[k]);//每次交换第j和k个元素,这样每个元素都曾出现在最前面过,然后递归剩下的元素;
Perm(list,k+1,m);//进入递归;
Swap(list[k],list[i]);//恢复原本元素的次序;
}
}
inline void Swap(int *a,int *b)//交换函数的定义,此处用内联函数可以节省内存
{
int temp=*a;
*a=*b;
*b=temp;
}
下面以{a,b,c}的全排列为例来说明这个算法:
{a,b,c}--->{a,b,c},第一次进入递归{a,(b,c)}--->{a,(b,c)},
第二次进入递归{a,b,(c)},此时k=m=2,输出"a,b,c",返回上一层的递归现场,恢复为{a,b,c}且j+1,
{a,b,c}--->{a,(c,b)},第三次进入递归{a,c,(b)},k=m=2,输出"a,c,b",返回上一层的递归现场,恢复为{a,b,c}且j+1,
{a,b,c}--->{b,a,c},第四次进入递归{b,(a,c)},
第五次进入递归{b,a,(c)},此时k=m,输出"b,a,c",返回上一层的递归现场,恢复为{b,(a,c)}且j+1,
{b,(a,c)}--->{b,(c,a)},第六次进入递归{b,c,(a)},k=m又输出"b,c,a",返回上一层的递归现场,恢复为{a,b,c}且j+1,
{a,b,c}--->{c,b,a},第七次进入递归(c,(b,a)),
第八次进入递归{c,b,(a)},此时k=m,输出"c,b,a",返回上一层的递归现场,恢复为{c,(b,a)}且j+1,
{c,(b,a)}--->{c,(a,b)},第九次进入递归{c,a,(b)},k=m又输出"c,a,b",返回上一层的递归现场,恢复为{a,b,c}且j+1,
执行到目前,j=4,for循环停止,算法结束.
标签:二次 问题 集合 n个元素 恢复 == oid print 设计
原文地址:http://www.cnblogs.com/likebyk/p/6814006.html