学习笔记:用递归实现全排列。
- 《算法笔记》的递归章节里有个例子,我觉得很好,全排列用递归实现,首先分析问题:全排列: 输出 1~n这n个整数能形成的所有排列。
如1、2、3 的全排列为
(1、2、3),(1、3、2),(2、1、3),(2、3、1),(3、1、2),(3、2、1)
这6种 - 递归一定要一个思想是把一个问题分解为同样但不同参数的若干子问题:
抄书太麻烦了,直接上代码,P115《算法笔记》
#include <cstdio>
const int maxn = 11;
//p为当前排列,vis记录整数x是否已在p中
bool vis[maxn] = {false};
int p[maxn];
int n;
void Fuc( int index){ //入口:当前处理排列的第index号
if(index == n+1){ //递归边界(出口):当前处理第n+1个数,表明n个数都处理完了
for(int i=1; i<=n; i++){
printf("%d ",p[i] ); //输出当前排列,返回就完事了
}
printf("\n");
return ;
}
for(int x=1; x<=n; x++){ //枚举1~n,看谁未访问的就填入p[index]
if(vis[x]==false){ //若x不在p[0]~p[index-1]中
p[index] = x; //把x加入当前排列序列
vis[x] = true; //记x已在p中
Fuc(index + 1); //处理排列的第index+1号位
vis[x] = false; //能到这一步说明已经处理完p[index]为x的子问题,
//换元状态继续枚举下一个x
}
}
}
int main()
{
n = 3; //以1~3的全排列举例
Fuc(1);
return 0;
}
自我总结:
递归,很美妙,简单即美。
递归最两大要素:递归边界(出口)和递归式(递归链条)。所以得把问题分解,分解成若干同源子问题。还有一点我觉得也很重要,入口,从哪开始,以哪个量作为递归函数一开始的参数。这往往决定了递归逻辑的设计。