本以为学会了递归,没想到用起来还是比较困难。遇到了一个全排列的题目,来再学习体验一下递归思想。
题目大意为输出数列1,2,…n的全排列。
如:1,2,3,的全排列为:
1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1
结题思路:
利用递归的思想,把问题的规模不断缩小,分成若干个子问题,那么这题就可以分为:
输出以1开头的全排列
扫描二维码关注公众号,回复:
4955309 查看本文章
输出以2开头的全排列
……
输出以n开头的全排列
这里设定一个储存当前排列的数组AeList,一个散列数组StatusTable,当数字X已经在数组AeList中时,StatusTable[X]为true.
然后,按顺序往数组AeList的第1~n位填数字。现在假设AeList[1]~AeList[index-1]位已经填好,正准备填第index位,则枚举
1~n,如果某个数X还没在AeList[1]~AeList[index-1]位中(即StatusTable[X]==false),则将X填入AeList[X]里,同时StatusTable[X]
设为false。这时开始处理下一位index+1位,即进入递归.递归结束后在将StatusTable[X]还原为false,这样每次递归结束后都让
StatusTable[X]还原为false,以便下让数组AeList去存储下一个以某个数开头的全排列。
#include<cstdio>
int n;//1~n个整数全排列
int AeList[10];//存储每次排列的序列
bool StatusTable[10]={0};//记录某个数是否已经在之前参与排列
void Arrange(int index)
{
if(index==n+1)//递归边界,如果已经处理了前n个数,前n个数的某次全排列已经完成
{
{
int i;
printf("[ ");
for(i=1;i<=n;i++)
printf("%d ",AeList[i]);
printf("]\n");
}
return;
}
int x;
for(x=1;x<=n;x++)//枚举1~n试图将x填入AeList[index](从全局来看是 以1开头的排列,以2开头的排列,……以n开头的排列 )
{
if(StatusTable[x]==0)//如果这个数没有参与过排列
{
AeList[index]=x;//另AeList的第index位为x,即把x加入当前排列
StatusTable[x]=1;//记录x的状态,表明其已经在排列中
Arrange(index+1);//处理下一位
StatusTable[x]=0;//处理完后还原状态,这样才能在返回上一次层时保证正确
}
}
}
int main()
{
n=3; //1~3的全排列
Arrange(1);//从 AeList[1]开始填
return 0;
}