一个不是很麻烦的递归函数,就可以把我给虐心了。
我还是很弱,在编程之路上,还有很多门槛等着我去跨越。
突然觉得这句话很适合我 “少年,你还有很长的路要走!!”
#include <iostream> //《菜鸟学递归函数之全排列-被虐心了》
#define MAX 10 //这里定义了预编译器变量 MAX 代表 10
using namespace std;
struct Set//这里定义了一个透明类struct,它仅仅是为了保存一个数组
{
int e[MAX];
int length; //length的含义是e[MAX]中已填充的数据
} stack; //在定义类Set的同时定义了它的对象stack,它是全局的供下面的递归函数操作
void fullArray(Set &set) //这个递归函数对目前没接触算法的我来说,姑且叫它虐心递归函数吧
{
if(set.length==1) //明白这个递归函数想要看懂那位大哥给的递归算式,基本意思
{//就是全排列是数字个数的阶乘n!n*(n-1)*(n-2)...
for(int i=0; i<stack.length; ++i) //回到递归,每当子序列的长度为一的时候,就达到一次递归探底,
cout<<stack.e[i]<<',';//也就是最后那个subset只有一个元素了,它的排列只有一种了,不
cout<<set.e[0]<<'\n'; //需要再为它递归了。然后从栈输出目前的排列。
}//每次递归探底之后,才会执行之后的--stack.length;语句,这时
else//把stack的顶层元素pop掉,拿其中一段过程来说,比如倒数两个subset
{//它们一个长度是2,一个是1,当回溯到第二个的时候,--stack.length
for(int i=0; i<set.length; ++i) //就执行了两次,把后面两个subset在stack里面的输入pop掉了,回溯多少层
{ //就pop掉多少元素,如果返回到了第一次调用函数的时候,这时候stack里面
stack.e[stack.length++] = set.e[i];//就只有一个元素了,那就是set.e[0],第一递归函数的for循环刚循环一次
Set subset = set; //这时候++i,进行第二次循环。最外层的递归函数执行set.length次,
subset.e[i]= subset.e[--subset.length];//再内一层的执行set.length-1次,依次减少,最内层执行一次,总共
fullArray(subset); //执行set.length的阶乘次,每次探底都输出一个排列,于是所有的排列都
--stack.length; //输出了。要理解递归函数,就在脑子里多自己推演一下递归展开跟
}//递归回溯发生的事情。
}
}
int main(){ //主函数里没什么好解释的,都是些基本语句
Set s;//创建了Set对象,后面把输入的数字放到它里面了,length是输入的数字个数
s.length = 0;
cout<<"Input\n";
while(1){
int temp;
cin>>temp;
if(temp==0)
break;
s.e[s.length++] = temp;
}
cout<<"Output\n";
fullArray(s);
cout<<"End\n";
::system("pause");
return 0;
}