连续两次递归调用的执行顺序
记住:参数M = 栈顶值。而不是Pop的值。 总结一下:
1.0 递归有点类似循环,不同之处是,递归的参数:函数指针 临时变量 参数 在栈里自动释放, 返回到第一次递归的地方继续执行。 2.0 比如:第一次rec(10),10进去之后执行rec函数,但是没执行完,先存着(压在栈里), 然后执行rec(9)。。。一旦执行到条件不满足,导致执行不到rec()函数了,循环停止了, 就开始弹出。即一直到能完整调用rec()函数之后,才开始反向。 3.0 即条件是拐点。 4.0 条件是难点: 如果把递归比喻成解方程: 相求a的值,必须知道b,想求b,又必须知道c...; 最后想求f必须知道g.正好g知道,直接求出。然后再回代,求f,e,d,c,b,a; g求完了,接着求f,别忘了你是f求了一半用到g了。 5.0 rec()执行完了不再进入循环,就要接着上一个继续执行。f还求一半呢,接着向下执行。
// 双递归函数 void rec(int M) // 在这里拷贝实参,进行入栈操作 { //为了区分这两个递归,分别为它们取个别名好了 if (M > 0) { rec(M - 1);//rec1---中断/回归 cout << "rec1 后面一句, 此时M = " << M << endl; rec(M - 10);//rec2---中断/回归 cout << "rec2 后面一句, 此时M = " << M << endl; } cout << "M = " << M << endl; return; } // 在此处执行出栈操作,即在这里改变M值 // 这里执行两步,第一步返回到rec1,继续向下执行代码; // 第二部,rec1继续执行出栈操作,改变m值
执行rec(10),结果如下: 分析: M一直等于栈顶的值
1. 调用rec(10), --- 10 拷贝入栈 2. 10>0, 继续执行rec(9), --- 9拷贝入栈 ...... 3. 一直执行到rec(1), 1入栈; 1>0, 执行rec(0),0入栈; 4. 但是,0>0不成立,执行输出语句" M = 0"; 5. 在程序结束语句,0出栈,栈顶变为m = 1,且返回至rec1继续执行, 打印rec后面一句,此时M = 1; 6. 接着,执行rec2(1-10)(m=1没有执行至结束,并没有出栈), 此时,rec1的出栈操作被打断, 执行rec2的入栈操作(-9拷贝入栈) 7. -9<0,不成立,直接执行"M = -9",-9出栈,此时栈顶为m=1;在程序结束语句, 回到rec2接着执行,m为栈顶值。 8. 输出"rec2 m = 1",再输出m=1,执行到程序结束语句,1出栈,m = (栈顶)2, 返回rec1继续执行下面语句。
例二:再以二叉树的先序遍历为例:
void PreOrderTraversal(BinTree BT) { if(BT) { PreOrderTraversal(BT->left); PreOrderTraversal(BT->right); } }
1.0 首先,A B D进栈,D->left不存在,进栈立马出栈(因为preOrderTraversal()执行完了) 但是D执行到一般去执行D->left了,你执行完了,我还没完呢,再返回到岔路的地方继续 执行我的D,但是又碰到岔路了,即开始执行preOrderTraversal(BT->right),BT->right 也不存在,进栈立马出栈,执行完了,又返回到岔路继续执行到结束了,直接D的递归也全部 完成了;但是,你D是我B憋到一半跑岔路了(就是执行了左岔路,但是右岔路没搞),继续回到 B的右岔路开始执行。
下一篇:
斐波那契数列——java实现