全排列算法(递归)
一直学习,有时候会感到厌烦,天天呆在自习室,把人都傻了。考研刚刚结束,打算把数据结构再复习复习,也给自己找点编程的东西。接受了朋友的建议,先从递归算法开始复习吧。
递归是一种机制,一种思想。有的问题本身就是递归定义的,例如求阶乘,二叉树……;有的问题表面上看来不是递归定义,但是也可以用递归来解决,我认为这有点像分治法,即减小问题的规模。实现递归,有两个必要条件,即1.确定递归公式;2.确定边界(终了)条件;
例1:求n个元素的全排列?
分析:按照排列组合的知识,我们知道结果有n!种。在这里,我为了便于自己分析,仅取[a,b,c],即令n=3。结果是:a,b,c;
a,c,b;
b,a,c;
b,c,a;
c,a,b;
c,b,a.
首先,上述结果可以分为三组:
1、a跟着{b,c}的全排列
2、b跟着{a,c}的全排列
3、c跟着{a,b}的全排列
接下来,我们认真分析,可以发现,在上面所分的三个小组,有可以用同样的思想处理,即:
1、a跟着{b,c}的全排列
(1)b跟着{c}的全排列
(2)c跟着{b}的全排列
2、b跟着{a,c}的全排列
与上相同……,嘿嘿,请自己想想吧
3、c跟着{a,b}的全排列
附上代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define SWAP(x,y,t) ((t)=(x),(x)=(y),(y)=(t)) 4 void perm(char [],int,int); 5 int main() 6 { 7 char list[]={'a','b','c'}; 8 perm(list,0,2); 9 return 0; 10 } 11 void perm(char list[],int i,int n) 12 { 13 int j=0,temp; 14 if(i==n) 15 { 16 for(;j<=n;j++) 17 printf("%c ",list[j]); 18 printf("\n"); 19 } 20 else 21 { 22 for(j=i;j<=n;j++) 23 { 24 SWAP(list[i],list[j],temp); 25 perm(list,i+1,n); 26 SWAP(list[i],list[j],temp); 27 } 28 } 29 }
为了表明意思,我在纸上模拟了递归调用的执行过程,发现结果如下:
a,b,c
a,c,b
b,a,c
b,c,a
c,b,a
c,a,b
细心的读者可能会发现,最后两行不太一样,跟我们分析的不同,但是,这就是程序执行的结果,因为,在把以b开头的结果输出后,往上一层跳时,把数组还原为[a,b,c],接下来,在处理以c开头的结果时,第一层循环,应该先把a与c交换,再向下递归调用~~~
附上图片: